假设我有一个库 foo ,它由模块 foo 和 util 组成,并具有以下源代码树:
foo/
foo.c
foo.h
util.c
util.h
库的公共API在 foo.h 中定义,所有全局标识符都正确地以foo_
或util_
为前缀。模块 util 仅由 foo 使用。为了防止与名为 util 的其他模块发生名称冲突,我想创建一个(静态)库,其中只有模块 foo 中的标识符可见。我怎么能这样做?
编辑:我已经非常广泛地搜索了互联网,但令人惊讶的是,这似乎是计算机科学中尚未解决的问题之一。
答案 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_
为前缀。这意味着名称冲突不太可能发生。