dllimport 和 dllexport
Dll 在需要暴露接口的头文件里添加 dllexport 声明,比如,
1 2 3 4 5 6 | #define DllExport __declspec( dllexport ) class DllExport C { int i; virtual int func( void ) { return 1; } }; |
注意,禁止对可导出类的成员显式使用 dllimport
和 dllexport
特性。
我们一般情况下会使用预定义宏控制 dll 接口的导入导出,比如,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #include <stdint.h> #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #ifdef __PROJECT_OS_WIN32__ #define PROJECT_API __stdcall #define DLLIMPORT_C extern __declspec(dllimport) #define DLLEXPORT_C __declspec(dllexport) #else #define PROJECT_API #define DLLIMPORT_C #define DLLEXPORT_C __attribute__((visibility("default"))) #endif // __PROJECT_OS_WIN32__ #ifdef __PROJECT_SOURCE__ #define PROJECT_EXPORT DLLEXPORT_C #else #define PROJECT_EXPORT DLLIMPORT_C #endif // __PROJECT_SOURCE__ PROJECT_EXPORT int PROJECT_API project_init( struct xxx**ctx, int x); |
这样,我们只要在 Dll 的工程里添加 __PROJECT_OS_WIN32__ 和 __PROJECT_SOURCE__ 预定义宏就可以导出 project_init 接口
同样,我们在使用的时候只要在项目中添加 __PROJECT_OS_WIN32__ 即可导入 project_init 接口,当然,项目中要包含相关接口的头文件
参考:
拓展:
上述第二个链接中提到了 .def 文件,添加该文件也是为了暴露接口,后续可以研究研究
更新:
.def 文件似乎对依赖的静态库暴露的函数无法起到限制作用
缘由:我们在项目中自编译了一个工具静态库,这个库里的函数是由 BASE_EXPORT 做前缀组成,我们在 CMakeLists 中使用 add_subdirectory 添加了子静态库后,最终编译出我们需要的可执行程序,在使用 dumpbin /exports 查看 exe 文件暴露的函数,发现除了预期的 main 函数,还有很多子库的函数,理论上这些子库是不应该暴露的
猜测:在没有编译子静态库时,我们是在主项目中直接调用子文件夹中的源码,那时并没有暴露子文件夹的函数,所以问题是出现在编译成静态库当中
我们知道静态库中所有的函数其实都是暴露给调用的项目的(动态库需要主动暴露出函数,即 dllimport),因为最终主项目在编译过程中,是在链接的过程中到静态库中找到对应的符号文件,而 BASE_EXPORT 并没有阻止主项目中的静态库函数暴露出来
相反,dll 动态库是可以做到这点,究其原因,得后续研究研究了
解决方法:因为静态库的函数是全暴露的,那么我们就不用 #define BASE_EXPORT __declspec(dllexport) 额外暴露的,最后发现主项目编译后没有暴露静态库的函数
旧的:
1 2 3 4 5 | #if defined(WIN32) #define BASE_EXPORT __declspec(dllexport) #else #define BASE_EXPORT __declspec(dllimport) #endif |
新的:
1 2 3 4 5 6 7 8 9 | #if defined(PROJECT_EXPORT) #if defined(WIN32) #define BASE_EXPORT __declspec(dllexport) #else #define BASE_EXPORT __attribute__((visibility("default"))) #endif #else #define BASE_EXPORT #endif |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
2022-11-08 std::vector<std::string> 与 char** 的转换
2019-11-08 使用GDI+(WIC)加载32位的位图或者PNG图片(具有透明通道)
2019-11-08 C++最快获取像素值