如何通过宏配置用同一份代码编译DLL和静态库且无需客户端额外传宏
该需求完全可以实现,核心是调整头文件的宏判断逻辑,取消客户端侧Windows平台默认添加的__declspec(dllimport)标记,即可同时兼容静态库和DLL的引用场景,无需客户端额外传入编译宏。
第一步:修改hash.h宏定义
替换原有的宏逻辑为如下内容:
#ifndef HASHH #define HASHH // 编译库本身时的逻辑 #if defined(BUILD) #if defined(STATIC) // 静态库编译场景 #define ADDAPI #define ADDCALL #define EXTERN extern #else // 动态库编译场景 #define EXTERN #ifdef _WIN32 #define ADDAPI __declspec(dllexport) #define ADDCALL __cdecl #else // 兼容非Windows平台的符号可见性配置 #define ADDAPI __attribute__((visibility("default"))) #define ADDCALL #endif #endif // 客户端引用头文件时的逻辑 #else #define EXTERN extern #ifdef _WIN32 // 客户端侧取消dllimport声明,同时兼容静态库、DLL两种链接方式 #define ADDAPI #define ADDCALL __cdecl #else #define ADDAPI #define ADDCALL #endif #endif /*** The sha3-256 hash function. @param buffer The buffer containing the data to be hashed. @param length The length of the buffer. @param digest The hash of the data in buffer. */ ADDAPI EXTERN int ADDCALL sha3_256(unsigned char* buf, unsigned long len, unsigned char* digest); #endif
第二步:保留原有编译逻辑无需修改
原来的Windows平台编译命令可以直接复用,仅需对静态库编译命令做极小的严谨性调整:
- 编译DLL:
gcc -c -D BUILD source\hash.c -o objects\hash.o ld -s -shared objects\hash.o -o hash.dll
- 编译静态库:
gcc -c -D BUILD -D STATIC source\hash.c -o objects\hash.o ar rcs hash.lib objects\hash.o
补充说明:静态库编译命令新增了
-D BUILD宏,和头文件的新逻辑匹配,原命令漏传该宏也能运行,补充后逻辑更规范。
可选进阶优化(保留DLL调用性能)
如果希望保留DLL场景下__declspec(dllimport)带来的调用性能提升,可以配合编译产物命名区分实现自动判断:
- 静态库编译后命名为
hash_static.lib,DLL对应的导入库命名为hash.lib - 在头文件客户端逻辑分支补充如下内容:
#ifdef _WIN32 #if defined(HASH_USE_STATIC) #define ADDAPI // 自动链接静态库,无需客户端手动配置链接参数 #pragma comment(lib, "hash_static.lib") #else #define ADDAPI __declspec(dllimport) // 自动链接DLL导入库,无需客户端手动配置链接参数 #pragma comment(lib, "hash.lib") #endif #define ADDCALL __cdecl #endif
需要使用静态库的客户端仅需定义HASH_USE_STATIC一个宏即可,相比原逻辑对用户更友好,也可以通过定制链接脚本进一步省略该宏定义。
内容的提问来源于stack exchange,提问作者user123
相关产品推荐
相关产品推荐

