隐藏库中的非API符号

时间:2017-09-05 15:14:25

标签: c posix ld static-linking object-files

假设我有一个库 foo ,它由模块 foo util 组成,并具有以下源代码树:

foo/
    foo.c
    foo.h
    util.c
    util.h

库的公共API在 foo.h 中定义,所有全局标识符都正确地以foo_util_为前缀。模块 util 仅由 foo 使用。为了防止与名为 util 的其他模块发生名称冲突,我想创建一个(静态)库,其中只有模块 foo 中的标识符可见。我怎么能这样做?

编辑:我已经非常广泛地搜索了互联网,但令人惊讶的是,这似乎是计算机科学中尚未解决的问题之一。

3 个答案:

答案 0 :(得分:2)

可能有其他可能的方法,但这里有一个:

您可以考虑在util.c中包含文件foo.c并使所有util函数/全局变量保持静态。即:

#include "util.c"
// ...

这与*.h文件的工作方式相同,它只是将整个源代码移植到foo.c,嵌套util.c并使所有静态数据可用。

当我这样做时,我将文件重命名为.inc(即util.c => util.inc)...

#include "util.inc"
// ...

...这是我在某个地方找到的旧约会,虽然它可能与汇编程序文件冲突,所以您必须自行决定。

修改

另一种方法可能需要特定于链接器的指令。例如,this SO answer details GNU's ld to achieve this goal。还有其他方法,列在同一个线程中。

答案 1 :(得分:0)

以下是GCC特定的。

您可以使用

标记每个实用程序功能
__attribute__((visibility ("hidden")))

将阻止它与另一个共享对象链接。

您可以使用

将其应用于一系列声明
#pragma GCC visibility push(hidden)
/* ... */
#pragma GCC visibility pop

或在编译对象时使用-fvisibility=hidden,这适用于没有明确可见性的声明(例如__attribute__((visibility))#pragma GCC visibility)。

答案 2 :(得分:0)

util.h中的每个变量和函数声明之前,定义一个宏常量,通过添加库前缀foo_来重命名声明的标识符,例如

#define util_x foo_util_x
extern int util_x;   

#define util_f foo_util_f
void util_f(void);

...

有了这些定义,代码的其他部分都不需要更改,并且目标文件util.o中的所有全局符号都将以foo_为前缀。这意味着名称冲突不太可能发生。