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]]
以避免使用宏和ifdef
s 用于特定目标?
【问题讨论】:
【参考方案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)的主要内容,如果未能解决你的问题,请参考以下文章
Windows 和 Linux 上的 C++ [[gnu::visibility("default")]] vs __declspec(dllexport)
无法从 Visual Studio 启动 gdb 以在 Windows 上的 Linux 子系统中远程调试 Linux C++ 项目