我正在编译和归档库(称之为libbar.a
)。该库中的关键转换单元使用void foo()
中定义的(非静态)函数foo.cpp
,该函数也被编译并放入库中。
我想避免这个void foo()
与我的代码库中的其他符号(使用该库)发生冲突。现在,你可以说 - 只是不要包含声明void foo()
的标题;但是 - 如果我确实在其他地方使用相同的void foo()
怎么办?尽管在我的整个代码库中只使用一次它更有效,但我实际上希望使用该库的人无视内部使用的void foo()
的实现细节。所以 - 我希望没有人能够在libbar.a
中查找该符号,但libbar.a
中的代码仍然可以使用它。
我怎样才能做到这一点?
注意:
foo
和我的库)都是C和/或C ++。假设它只是C-C或C ++的答案也是相关的。void bar_foo()
),或将void foo()
放入命名空间,则可能会产生预期效果。但我不需要这样做,即我需要继续使用void foo()
的相同代码而不做任何更改。我只愿意改变使用void foo()
和构建机制的库代码中的东西。答案 0 :(得分:2)
如果您非静态地编译库(创建.so或.dll),则可以这样做。您可以选择要导出的符号:基本上,您隐藏所有符号并将属性添加到公共符号。
你可以用这种MACRO来实现这个目标:
#ifdef BUILD_STATIC_LIB
# define LIB_EXPORT
#elif (defined BUILD_DYN_LIB)
# if (defined __WIN32__) || (defined _WIN32) || defined(__CYGWIN__)
# ifdef __GNUC__
# define LIB_EXPORT __cdecl __attribute__((dllexport))
# else
# define LIB_EXPORT __cdecl __declspec(dllexport)
# endif
# else
# define LIB_EXPORT __attribute__ ((visibility ("default")))
# endif
#else
# if (defined __WIN32__) || (defined _WIN32) || defined(__CYGWIN__)
# ifdef __GNUC__
# define LIB_EXPORT __cdecl
# else
# define LIB_EXPORT __declspec(dllexport)
# endif
# else
# define LIB_EXPORT
# endif
#endif
准备所有公共符号MACRO LIB_EXPORT
,并使用-DBUILD_DYN_LIB
构建源代码。
在Linux上,添加链接器标志-fvisibility=hidden
但是如果你想用静态库(.a)实现这一点,那么唯一正确的方法是将每个私有函数放在命名空间中......
同样使用静态库可能会导致危险":如果您的应用程序提供了与静态库中提供的符号相同的符号,则链接器将不会发出警告(至少在默认情况下),应用程序将被链接/创建。 链接器将从应用程序中选择符号,而不是从静态库中选择。
如果可以,您可以使用此处描述的技巧修补libbar.a的所有符号:https://stackoverflow.com/a/6940389/808101
在您的应用程序中,如果您需要使用" patched"中的符号(函数)。 libbar.a,您必须在符号名称前加上--prefix-symbols