如何在 C++ 静态库中隐藏符号?

Posted

技术标签:

【中文标题】如何在 C++ 静态库中隐藏符号?【英文标题】:How to hide symbols in c++ static library? 【发布时间】:2019-05-16 11:00:57 【问题描述】:

我会调整情况。 在这个问题中,我使用 Ubuntu 16.04 和 GCC 6.5.0 和 CMake 3.13.2。

我有 4 个静态库和一个可执行文件:ABCDmainAint add(int, int) 只需添加 2 个给定的整数。 Bint addb(int, int) 只需从 A 调用 addCint add(int, int) 乘以 2 个给定的整数。 Dvoid print()B 调用 addb 和从 C 调用 add。 而main 只需调用print()。 所有这些函数都将声明和定义拆分为.cpp.hpp

方案:

A (add)
  |
B (addb)    C (add)
  |           |
  |___________|
        |
      D (print)
        |
       main

我必须怎么做才能从A 符号中隐藏add?因为我在链接main时有多重定义。

如果我只是使用 cmake 构建,它会在两种情况下从 C 调用 add(参见 Dprint())。我将B 与 ld (ld -static) 链接,但现在我有两个问题:

乘以add的定义(首先定义在Ano .eh_frame_hdr table will be created

另外,我尝试使用 cmake 制作 AC SHARED,但它像以前一样从 C 调用 add

我除了 B 将是“完整的”静态库,没有 *UND*,如果我调用 addb,它将从 A 调用 addadd 将从 C 调用。 谢谢!

【问题讨论】:

这无法完成。您必须使用唯一的符号名称,以避免歧义。 这就是您要在 C++ 中使用命名空间的确切原因。如果多个库因为不使用不同的命名空间而输出相同(损坏的)符号名称,那么您就不走运了。 你不能破坏one definition rule。每个符号只能定义一次。 C++ 和库的典型解决方案是使用类或命名空间。然后你可以有例如namespace A int add(int, int); namespace C int add(int, int); 【参考方案1】:

您违反了definition rule。简而言之,就是每个函数(1) 只能定义一次(除非声明为内联,在这种情况下,所有定义都必须相同)。

您尝试做的是惯用的命名空间。您的 A、B、C 库将在适当的命名空间中声明它们的所有函数。

类似

namespace A

   int add(int lhs, int rhs);
;

namespace C

   int add(int lhs, int rhs);

(1) 单一定义规则不仅仅与函数有关。在程序级别,它也适用于变量,并且在给定的翻译单元中,它也扩展到模板、类类型和枚举。

【讨论】:

以上是关于如何在 C++ 静态库中隐藏符号?的主要内容,如果未能解决你的问题,请参考以下文章

与静态库中的 std::string 相关的 C++ 未定义符号

如何为linux静态库隐藏本地符号

使用 Clang 作为编译器构建 Android 项目时从静态库中隐藏符号

如何在 C++ 共享库中隐藏业务对象的实现细节并提供接口

如何使静态库中的 gcc 链接强符号覆盖弱符号?

如何防止静态库中的所有符号加载以及为什么在链接静态库时导出相同.o文件中的其他符号进行测试