Windows下DLL_EXPORT宏不能直接用于Linux,因为Windows需__declspec(dllexport)显式导出,而Linux默认导出非static符号,且visibility控制逻辑不同;硬套会导致编译失败或导出异常。

Windows 下 DLL\_EXPORT 宏为什么不能直接用
Windows 动态库需要显式标记导出符号(函数、类),否则链接器看不到;Linux/macOS 的共享库默认导出所有非 static 符号,加 attribute((visibility("default"))) 是为了缩小导出面,提升安全性和加载速度。直接写死 DLL_EXPORT 宏在 Linux 上不仅多余,还可能干扰 visibility 控制逻辑。
- Windows:必须用
declspec(dllexport)导出,declspec(dllimport)导入 - Linux/macOS:靠编译器 flag(
-fvisibility=hidden)配合attribute((visibility("default")))显式导出 - 同一宏名在不同平台语义不一致,硬套会编译失败或导出异常
推荐的跨平台导出宏定义方式
用预处理器区分平台,统一宏名(如 MYLIB_API),让使用者只关心“这里要不要导出”,不感知底层机制:
#ifdef _WIN32
#ifdef MYLIB_BUILDING_DLL
#define MYLIB_API __declspec(dllexport)
#else
#define MYLIB_API __declspec(dllimport)
#endif
#else
#ifdef __GNUC__
#define MYLIB_API __attribute__((visibility("default")))
#else
#define MYLIB_API
#endif
#endif
-
MYLIB_BUILDING_DLL需在构建动态库时由 CMake 或编译命令定义(如-DMYLIB_BUILDING_DLL) - Linux/macOS 下未定义
GNUC的情况极少,但留空比报错更安全 - 不要省略
attribute的括号——漏掉双括号(如写成attribute(visibility("default")))会导致 GCC 拒绝编译
头文件中声明导出符号的正确姿势
导出宏必须放在返回类型前,且类/函数声明需完整可见(不能只在 .cpp 里加):
class MYLIB_API MyClass {
public:
MyClass();
void doSomething();
};
<p>MYLIB_API void myFunction(int x);</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/gongju/2823" title="C++14"><img
src="https://img.php.cn/upload/manual/001/431/639/6ac8b33c327c4749.png" alt="C++14" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/gongju/2823" title="C++14" class="overflowclass">C++14</a>
<p class="overflowclass">C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。</p>
</div>
<a rel="nofollow" href="/xiazai/gongju/2823" title="C++14" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
- 类模板不能直接导出(实例化发生在使用端),需对常用特化显式导出:
template class MYLIB_API std::vector; - 内联函数(
inline)加MYLIB_API无意义,导出的是符号地址,而内联函数通常不生成独立符号 - 如果头文件被同时用于构建 DLL 和调用方,确保
MYLIB_BUILDING_DLL只在构建 DLL 时定义,否则调用方会误用dllexport
CMake 中控制 MYLIB_BUILDING_DLL 的关键点
CMake 不会自动帮你定义这个宏,必须手动加:
add_library(mylib SHARED ${SOURCES})
target_compile_definitions(mylib PRIVATE MYLIB_BUILDING_DLL)
- 用
PRIVATE(不是PUBLIC),避免污染下游依赖项的编译环境 - 静态库不用定义该宏,也不应加
MYLIB_API(否则 Windows 下会链接失败) - 若项目同时提供静态/动态版本,建议用不同 target 名(如
mylib_shared/mylib_static),避免宏冲突
跨平台导出宏真正难的不是写法,而是确保构建系统、头文件、链接顺序三者严格对齐——少一个 PRIVATE,多一个 inline,或者忘了在 .h 里加宏,都可能导致 Linux 下符号找不到、Windows 下出现 LNK2019。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










