如何在编译时判断SOME_MACRO是__declspec(dllimport)还是dllexport?
SOME_MACRO是__declspec(dllimport)还是__declspec(dllexport)? 首先得给你浇个小冷水:你没法直接用#if SOME_MACRO == __declspec(dllimport)这种写法实现编译时判断。原因很直白:__declspec是MSVC(以及部分兼容它的编译器)独有的编译器扩展关键字,它不属于C/C++预处理器能直接处理的“常量”范畴——预处理器根本看不懂这种带编译器语法的宏内容,自然没法做等式比较。
不过别慌,有几种靠谱的替代方案能帮你实现需求,尤其是针对你说的大型第三方库场景:
1. 找根控制宏,直接基于它判断
这是最稳妥的办法。大型第三方库通常不会直接硬写__declspec,而是通过一个根宏(比如LIB_NAME_EXPORTS、BUILD_DLL这类常见命名)来切换import/export状态。
比如原库的代码大概率是这样的:
#ifdef MY_BIG_LIB_EXPORTS #define SOME_MACRO __declspec(dllexport) #else #define SOME_MACRO __declspec(dllimport) #endif
那你根本不需要去解析SOME_MACRO的内容,直接用#ifdef MY_BIG_LIB_EXPORTS就能判断当前是export还是import场景:
#ifdef MY_BIG_LIB_EXPORTS // 这里是dllexport场景的代码 #else // 这里是dllimport场景的微调代码 #endif
如果不知道根宏叫什么,你可以用编译器的预处理输出功能(MSVC用/E参数,GCC/Clang用-E)生成预处理后的文件,搜SOME_MACRO的定义,就能找到对应的控制开关。
2. 用预处理器字符串化技巧间接判断
如果你实在找不到根宏,或者没法依赖它,那可以借助预处理器的字符串化操作,把SOME_MACRO的内容转成字符串后比较。写个辅助宏就能实现:
// 辅助宏:把传入的内容转成字符串 #define STRINGIZE(x) #x #define STRINGIZE_MACRO(x) STRINGIZE(x) // 然后就可以在编译时判断了 #if defined(SOME_MACRO) #if STRINGIZE_MACRO(SOME_MACRO) == "__declspec(dllimport)" #pragma message("当前是dllimport场景") // 你的微调代码 #elif STRINGIZE_MACRO(SOME_MACRO) == "__declspec(dllexport)" #pragma message("当前是dllexport场景") // 默认逻辑代码 #else #pragma message("SOME_MACRO的值未知") #endif #endif
这种方式在MSVC下完全可靠,你可以先写个极小的测试程序验证:
// test_dll_macro.cpp #define SOME_MACRO __declspec(dllimport) #define STRINGIZE(x) #x #define STRINGIZE_MACRO(x) STRINGIZE(x) #if STRINGIZE_MACRO(SOME_MACRO) == "__declspec(dllimport)" #error "检测到dllimport" #else #error "未检测到dllimport" #endif
用MSVC编译这个文件,如果输出error C2312: '检测到dllimport',就说明这个方法有效,你可以放心用到库中。
3. 手动注入辅助宏(如果允许修改库代码)
如果你能修改第三方库的代码,可以在定义SOME_MACRO的地方同时定义两个辅助常量宏:
#ifdef MY_BIG_LIB_EXPORTS #define SOME_MACRO __declspec(dllexport) #define SOME_MACRO_IS_EXPORT 1 #define SOME_MACRO_IS_IMPORT 0 #else #define SOME_MACRO __declspec(dllimport) #define SOME_MACRO_IS_EXPORT 0 #define SOME_MACRO_IS_IMPORT 1 #endif
之后你就可以直接用#if SOME_MACRO_IS_IMPORT来做判断,这种方式最清晰,也不会有字符串化的兼容性问题。
内容的提问来源于stack exchange,提问作者SiLiKhon

