C++ [[gnu::visibility("default")]] 和 Windows、Linux上的 __declspec(dllexport) 的区别在哪里?

7

我需要在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,它们是同义词(我想),所以问题是是否有一个[[gnu::attribute]]用于__declspec(dllimport),以避免为特定目标使用宏和ifdef
1个回答

5
符号可见性与dllexport微妙不同 - 主要原因是在Windows下使用mingw/cygwin编译.dll时,链接器的默认行为是选项-export-all-symbols - 即它将默认自动导出你的.dll中的所有内容
您可以通过使用.def文件或将__declspec((dllexport))__attribute((dllexport))放置在任何例程上来更改此行为(即如果指定要导出单个符号,则仅导出声明为导出的符号)。如果库中有很多符号,则这可以在dll加载时间显着提高性能。
如果要使用等效的C++属性,则使用[[gnu::dllexport]]

所以,使用dllexport来防止你的.dll导出全局变量。

类似地,你可以使用[[gnu:dllimport]]来导入外部例程。

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


据我所知,[[gnu::dllexport]]仅适用于GCC,是吗?是否有类似的东西在Clang和MSVC下也能工作? - Andrii Zymohliad
1
它也可以在clang上运行。MSVC没有相应的功能,因此,如果您想要跨平台兼容的代码,您可能需要使用宏。所有三个编译器都支持使用__declspec((dllexport|dllimport)),所以您可以使用它,但这不是“干净”的C ++。如果您想要保证平台兼容的代码,只能依靠标准指定的[[ ]]属性。 - Anya Shenanigans

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接