是否可以将资源构建到静态库中,并通过简单地链接到库来重用它们?
我主要考虑的是你在库中调用一个函数然后访问资源的情况.
在Visual C++(2008)中,在静态库中使用资源(图像,对话框等)所需要做的唯一事情就是在项目中包含静态库的关联.res文件.这可以在"项目设置/链接器/输入/附加依赖性"中完成.
使用此解决方案,静态库的资源将打包到.exe中,因此您不需要额外的DLL.遗憾的是,Visual Studio不会像.lib文件那样自动包含.res文件(当使用"项目依赖项" - 特性时),但我认为这个额外的小步骤是可以接受的.
我已经为这个解决方案寻找了很长时间,现在让我感到惊讶的是这很简单.唯一的问题是它完全没有记录.
它可以完成,但是非常痛苦:你不能通过简单地链接静态库来实现它.
考虑一下:资源嵌入在EXE或DLL中.当静态库中的某些代码调用(例如)LoadIcon时,它将从与其链接的EXE或DLL中获取资源.
因此,如果您的静态库需要资源可用,那么您有几个选择:
您可以让库在运行中构建它们,然后使用(例如)CreateDialogIndirect
.请参阅Raymond Chen的"在运行时构建对话框模板".
您可以将它们作为简单数组(即)嵌入库中char my_dialog_resource[] = { .... };
,然后使用(例如)CreateDialogIndirect
.您可能需要查找(或编写)从.RES
文件转换为文件的实用程序.CPP
.
您可以使用资源脚本(.RC
文件)和相应的头文件来发送LIB 文件.然后你就#include
相关了.您需要为LIB保留一系列资源ID,以便它们不会与主EXE或DLL的资源ID冲突.这是MFC用作静态库时的作用.或者您可以使用字符串资源ID(这不适用于STRINGTABLE
资源).
您的静态库可以附带单独的资源DLL.
我刚刚使用MS Visual Studio编译器完成了这项工作.我们将一些遗留项目从DLL转换为静态库.其中一些DLL中嵌入了对话框或字符串资源.通过"TEXTINCLUDE"机制将它们包含在主应用程序的RC脚本文件中,我能够将这些DLL的.RC脚本编译到我们的主应用程序中.我发现通过直接编辑RC文件来实现这一点最简单,但Visual Studio也提供了更多"向导"机制.其他编译器中的实现很可能不同.
要直接操作主RC脚本:
0.1.在"2 TEXTINCLUDE"部分中,包含定义库的资源ID的头文件.语法是
2 TEXTINCLUDE BEGIN "#include ""my_first_lib_header.h""\r\n" "#include ""my_second_lib_header.h""\0" END
0.2.在"3 TEXTINCLUDE"部分中,包含库中的RC脚本.
3 TEXTINCLUDE BEGIN "#include ""my_first_library.rc""\r\n" "#include ""my_second_library.rc""\0" END
第3步和第4步应该会自动发生,但我发现自己输入它们更可靠,而不是依靠Microsoft的资源脚本编译器来处理事情.
0.3.将库资源定义的头文件添加到只读符号列表中.此列表通常位于文件顶部附近.
#define APSTUDIO_READONLY_SYMBOLS #include "my_first_lib_header.h" #include "my_second_lib_header.h" #undef APSTUDIO_READONLY_SYMBOLS
0.4.在APSTUDIO_INVOKED部分中包含库的RC脚本.这通常位于文件的底部.
#ifndef APSTUDIO_INVOKED #include "my_first_library.rc" #include "my_second_library.rc" #endif
您也可以通过Visual Studio IDE自动执行所有这些操作,但我发现它并不总是适用于我预期的情况.
在Visual Studio中打开"资源视图"窗口.
右键单击主应用程序的资源文件,然后从上下文菜单中选择"Resource Includes ...".
在标有"只读符号指令"的框中,添加.h文件的include语句,用于定义库的资源ID.
在标有"编译时指令"的框中,添加库的.rc脚本的include语句.
点击没关系.您可能还希望手动触发RC脚本编译,以确保它发生.
如果库的资源脚本引用磁盘上的任何文件(文本文件,图标文件等),则需要确保主应用程序项目知道在哪里找到它们.您可以将这些文件复制到应用程序可以找到它们的某个位置,也可以在编译器设置中添加其他包含路径.
要添加其他包含路径:
打开主应用程序的属性对话框.
从左侧导航窗格中选择"Configuration Properties/Resources/General".
在属性列表中,输入"其他包含目录"旁边的任何相关路径.