ysa*_*sap 7 c linux private global-variables shared-libraries
我正在写一个C(共享)库.它起初是一个单独的翻译单元,我可以在其中定义几个static全局变量,以便从外部模块中隐藏.
现在库已经增长,我想将模块分解为几个较小的源文件.问题是现在我有两个选项用于提到的全局变量:
在每个源文件中都有私有副本,并通过函数调用以某种方式同步它们的值 - 这将非常快速地变得非常丑陋.
删除static定义,因此变量在所有翻译单元中共享extern- 但是现在,如果在那里进行了所需的声明,则链接到库的应用程序代码可以访问这些全局变量.
那么,是否有一种巧妙的方法可以在多个特定的翻译单元之间共享私有全局变量?
您需要GCC 的可见性属性扩展.
实际上,类似于:
#define MODULE_VISIBILITY __attribute__ ((visibility ("hidden")))
#define PUBLIC_VISIBILITY __attribute__ ((visibility ("default")))
Run Code Online (Sandbox Code Playgroud)
(你可能想要#ifdef上面的宏,使用一些配置技巧àla autoconf和其他autotools ;在其他系统上你只需要空的定义,比如#define PUBLIC_VISIBILITY /*empty*/等等......)
然后,声明一个变量:
int module_var MODULE_VISIBILITY;
Run Code Online (Sandbox Code Playgroud)
或功能
void module_function (int) MODULE_VISIBILITY;
Run Code Online (Sandbox Code Playgroud)
然后,您可以在共享库中使用module_var或调用module_function,但不能在外部使用.
另请参阅GCC 的-fvisibility代码生成选项.
顺便说一句,你也可以用你的编译整个图书馆-Dsomeglobal=alongname3419a6,并使用someglobal像往常一样; 要真正找到它,您的用户需要将相同的预处理器定义传递给编译器,并且您可以使名称alongname3419a6随机且不可能足以使碰撞不可能.
PS.这种可见性特定于GCC(可能还有ELF共享库,例如Linux上的那些).如果没有GCC或共享库之外它将无法工作....因此非常特定于Linux(即使其他一些系统,也许是带有GCC的Solaris).可能一些其他编译器(clang来自LLVM)也可能支持Linux上的共享库(不是静态库).实际上,真正的隐藏(对单个共享库的几个编译单元)主要由链接器完成(因为ELF共享库允许).
最简单的(“老派”)解决方案是简单地不在预期的公共标头中声明变量。
将您的库头拆分为“header.h”和“header-internal.h”,并在后一个中声明内部内容。
当然,您还应该注意保护库全局变量的名称,以免与用户代码冲突;大概您已经有一个用于此目的的函数的前缀。
您还可以将变量包装在 a 中struct,以使其更清晰,因为那时只有一个实际符号是全局可见的。