8

C++ 模块 TS 为消除预处理器、缩短编译时间以及通常支持更健壮、模块化的 C++ 代码开发(至少对于非模板代码)提供了极好的工具。

底层机制提供对普通程序中符号的导入和导出的控制。

然而,为两种动态加载开发库存在一个主要问题:启动时加载和运行时加载。这个问题涉及从库中导出符号,这通常在可见性方面进行讨论。

通常,并非所有用于构建动态链接库的翻译单元的外部符号都应该对用户可见。此外,对于运行时加载,尤其是插件概念,必须从许多同时加载的库中导出相同的符号。

在 Windows 上使用语言扩展

 __declspec(dllexport)
 __declspec(dllimport)

作为符号属性附加在源代码中,最近在 unix 平台上的 gcc 和 clang 系统上,使用

__attribute__((visibility("default")))
__attribute__((visibility("hidden"))) 

旨在支持旨在由图书馆公开的符号的提供和使用。使用这些是复杂而混乱的:在 Windows 上,必须在编译库时使用宏来导出符号,但在使用时导入它们。在 unix 平台上,必须将可见性设置为导出和导入符号的默认值,编译器根据是否找到定义自行决定:编译器必须调用

-fvisibility=hidden 

转变。静态链接不需要导出/导入属性,并且可能应该将其宏化为空字符串。编写代码并摆弄构建系统以使这一切正常工作,特别是考虑到在编译库翻译单元期间#includes 必须具有正确的符号可见性设置非常困难,存储库中所需的文件结构一团糟,源代码乱七八糟使用宏,一般来说..整个事情都是一场灾难。几乎所有开源存储库都无法正确导出动态链接的符号,并且大多数程序员不知道动态库代码结构(使用两级命名空间)与静态链接有很大不同。

可以在此处看到如何执行此操作的示例(希望是正确的):

https://github.com/calccrypto/uint256_t

这个存储库曾经有 2 个头文件和 2 个实现文件,构建库的用户会看到 2 个头文件。现在有 7 个头文件和 2 个实现文件,构建库的用户将看到 5 个头文件(3 个带有扩展名include表示它们不被直接包含)。

所以在冗长的解释之后,问题是:最终的 C++ 模块规范是否有助于解决动态链接符号的导出和导入问题?我们能否期望能够为共享库进行开发,而不会使用供应商特定的扩展和宏污染我们的代码?

4

0 回答 0