我正在从一组静态库中构建一个DLL,而我遇到的问题是只导出了部分类。
我正在做的是使用预处理器定义声明我想要导出的所有符号,如:
#if defined(MYPROJ_BUILD_DLL)
//Build as a DLL
# define MY_API __declspec(dllexport)
#elif defined(MYPROJ_USE_DLL)
//Use as a DLL
# define MY_API __declspec(dllimport)
#else
//Build or use as a static lib
# define MY_API
#endif
例如:
class MY_API Foo{
...
}
然后我使用MYPROJ_BUILD_DLL
和&构建静态库MYPROJ_USE_DLL
未定义导致构建静态库。
在另一个版本中,我从这些静态库中创建了一个DLL。所以我定义MYPROJ_BUILD_DLL
导致我要导出的所有符号都归结为__declspec(dllexport)
(这是通过在DLL项目源文件中包含所有静态库头来完成的。)
修改
关于未加密符号的注意事项:链接器选项保留未引用数据(/OPT:NOREF
)和不删除冗余COMDAT(/OPT:NOICF
)已设置,以便不会删除未引用的符号。
好的,现在问题。当我使用这个新的DLL时,我会得到未解析的外部因素,因为不会导出类的所有符号。例如,在这样的类中:
class MY_API Foo{
public:
Foo(char const* );
int bar();
private:
Foo( char const*, char const* );
};
仅导出Foo::Foo( char const*, char const*);
和int Foo::bar();
。怎么可能?由于例如,我可以理解整个课程是否缺失我忘了在DLL-build中包含标题。但它只是部分缺失。
另外,假设Foo::Foo( char const*)
未实施;然后DLL构建将有未解决的外部错误。但是构建很好(我还在没有实现的情况下仔细检查了声明)。
注意:我合并的静态库的组合大小在30MB的范围内,生成的DLL为1.2MB。
我正在使用Visual Studio 9.0(2008)来构建所有内容。 取决于以检查导出的符号。
修改 对于那些想知道为什么我不只是从每个静态库构建一个DLL的人:我不能因为它们相互交叉引用(这就是为什么我需要将它们组合在一个单独的DLL中)。我知道,这太可怕了,我无法理解它背后的逻辑。
答案 0 :(得分:3)
请记住,当您链接到静态LIB时,默认情况下链接器只会提取客户端(在本例中是 DLL )实际引用的函数,类和数据。
所以会发生这样的事情:
修复:
什么不能解决它:
作为旁注:
答案 1 :(得分:2)
问题肯定是你在DLL项目中使用已经构建的静态.lib。这不起作用,您必须重建 .lib,以便函数获取__declspec(dllexport)声明符,并由链接器导出。
此时,首先创建.lib的DLL兼容版本并不是那么有用。只需创建两个项目,一个创建静态.lib,另一个创建DLL。从技术上讲,仍然可以在DLL项目中使用静态.lib,但是您必须使用.def文件导出函数。如果图书馆有大量出口,这可能是高度维护。
答案 2 :(得分:1)
这可能已经太晚了,但OP的抱怨是私有方法(析构函数)没有从dllexport
'd类导出。这不正常吗?不允许外部用户调用私有方法。