Windows 和 Linux 上的 C++ [[gnu::visibility("default")]] vs __declspec(dllexport)

Posted

技术标签:

【中文标题】Windows 和 Linux 上的 C++ [[gnu::visibility("default")]] vs __declspec(dllexport)【英文标题】:C++ [[gnu::visibility("default")]] vs __declspec(dllexport) on Windows and Linux 【发布时间】:2014-02-15 15:10:18 【问题描述】:

我需要用 C++ 制作一些共享库,并且我使用 linux 作为我的开发人员操作系统。我知道如果我想通过dlsym/LoadLibrary 加载符号,我需要使它们可见。所以在linux中我所有的符号都遵循这个模式:

extern "C" [[gnu::visibility("default")]] void f();

我在启用 C++11 的情况下使用了 clang,并且能够在我的主机程序中加载 f。当我迁移到 Windows 时,我使用了启用 C++11 的 GCC 4.8.2,并且该模式在 Windows 机器上也可以使用LoadLibrary。 (我需要将 C++11 用于新的属性语法)。我知道在 Windows 上我需要使用 __declspec(dllexport) 从共享库中导出符号。所以现在怎么办? __declspec(dllexport) 不再需要了吗?

编辑:

我发现here 是同义词(我认为)所以问题是__declspec(dllimport) 是否有[[gnu::attribute]] 以避免使用宏和ifdefs 用于特定目标?

【问题讨论】:

【参考方案1】:

符号可见性与dllexport略有不同——主要原因是当你在Windows下mingw/cygwin下编译.dll时,默认behaviour of the linker是选项-export-all-symbols——即默认情况下,它会自动从您的.dll 导出所有内容

您可以通过使用.def 文件或将__declspec((dllexport))__attribute((dllexport)) 放在any 例程上来更改此行为(即,如果您指定要导出单个符号,则仅导出声明为导出的符号)。如果您的库中有很多符号,这可以在 dll 加载时显着提高性能。

如果要使用等效的C++ 属性,则使用[[gnu::dllexport]]

所以,是的,使用dllexport 来阻止您的.dll 输出世界。

以类似的方式,您可以使用[[gnu:dllimport]] 导入外部例程。

阅读文档时要小心;它实际上说的是,当您使用 dllexport 属性时,它还会触发 visibility:default 行为,除非它被覆盖。

【讨论】:

据我了解,[[gnu::dllexport]] 仅适用于 GCC,不是吗?有没有这样的东西,也可以在 Clang 和 MSVC 下工作? 它也适用于 clang。 MSVC 没有同等功能,因此如果您想要全面兼容的代码,您可能不得不求助于宏。所有三个编译器都支持使用__declspec((dllexport|dllimport)),所以你可以使用它,但它不是“干净的”C++。如果要保证平台兼容代码,则只能依赖标准指定的[[ ]] 属性。

以上是关于Windows 和 Linux 上的 C++ [[gnu::visibility("default")]] vs __declspec(dllexport)的主要内容,如果未能解决你的问题,请参考以下文章

c++ 11个线程在linux和windows上的不同行为

Windows 和 Linux 上的 C++ [[gnu::visibility("default")]] vs __declspec(dllexport)

无法从 Visual Studio 启动 gdb 以在 Windows 上的 Linux 子系统中远程调试 Linux C++ 项目

C++ printf %p 说明符在 Linux 和 Windows 中的行为不同

C++ u8 文字 - Windows 上的意外编码

C++ Linux 代码破坏了 Windows 构建,因为缺少标头意味着函数未定义