MSVC中将静态库链接到DLL时是否需要导出静态库成员?
问题解答
1. 静态库未继承DLL项目的预定义宏属于正常现象
MSVC中每个项目的编译配置是完全独立的,预处理器定义属于项目级配置,不会在不同项目间继承。你在MyNativeDLL项目中设置的MY_PROJECT_DLL宏,仅作用于该项目自身的源码编译,Interface.lib、System.lib作为独立的静态库项目,编译时无法读取到DLL项目的宏定义,因此构建日志输出Building with DLL imports是符合预期的。
2. 需要添加导出标识的成员范围
将静态库打包进DLL的场景下,仅需导出需要被DLL外部调用的符号即可:
- 接口类
IInstance的普通构造、析构、虚函数不需要导出,虚函数依赖运行时虚表寻址,不需要显式导出即可正常调用 - 代码中的静态成员
static API_TYPE const ModuleCategory category需要加导出标识,静态成员属于直接寻址调用,外部调用方需要获取该符号的实际地址 - 内部实现类
DefaultInstance不需要任何导出标识,不需要对外暴露
3. 给静态库添加MY_PROJECT_DLL定义的方案可行
只要严格控制宏的生效边界,该方案是行业通用的标准实现:
- 编译需要打包进DLL的
Interface.lib、System.lib时,必须开启MY_PROJECT_DLL定义:静态库不会自行处理导出标记,只会将标记保留在目标文件中,后续DLL链接这些静态库时,会自动把标记为__declspec(dllexport)的符号加入DLL导出表 - 编译仅引用头文件、调用DLL接口的外部项目时,禁止定义
MY_PROJECT_DLL:此时API_TYPE会被解析为__declspec(dllimport),可正确从DLL导入对应符号 - 你当前遇到的外部符号未解析问题,通常是两种原因导致:一是需要导出的静态成员仅在头文件声明、未在cpp文件中实现;二是宏的生效边界配置错误,要么是静态库编译时未开
MY_PROJECT_DLL,要么是外部调用方误定义了MY_PROJECT_DLL
如果你不想给静态库单独配置宏,也可以选择在DLL项目中添加.def导出定义文件,手动列出需要导出的符号,两种方案均可以实现需求。
内容的提问来源于stack exchange,提问作者mike
相关产品推荐
相关产品推荐

