首页 > 解决方案 > 库中所有符号的显式名称修饰(也称为名称修饰)

问题描述

有没有办法在用 c(或 cpp)编写的库中显式地进行名称修饰(也称为名称修饰)。我希望我的共享库的所有符号的名称都被修饰。

考虑这个问题: 应用程序中不同版本的两个库在这个问题中, 如果我可以明确地将它们的所有名称都弄乱了,我想我可以解决这个问题。gcc 编译器本身可能有一些选项可以做到这一点。

标签: c++clinuxshared-librariesstatic-libraries

解决方案


你的问题是:

有没有办法在用 c(或 cpp)编写的库中显式地进行名称修饰(也称为名称修饰)。我希望我的共享库的所有符号的名称都被修饰。

但是,我怀疑您不恰当地使用了术语名称修饰。名称修改与库发布版本无关。如果您打算对库中导出的每个对象进行版本控制,那么有很多问题需要回答。就个人而言,我会使用版本化的命名空间——但这只是因为我(还)没有被它所困扰。这是一个简单的例子:

namespace mylibrary {
namespace v1 {
class foo {};
}
using foo = v1::foo;
}

mylibrary::foo f; // mylibrary::v1::foo

...然后在以后的版本中...

namespace mylibrary {
namespace v1 {
class foo {};
}
namespace v2 {
class foo;
}
using foo = v2::foo;
}
mylibrary::foo newer_f; // mylibrary::v2::foo
mylibrary::v1::foo older_f;

当然,你可以有很多排列。并且有很多警告,特别是如果您有模板代码或使用 ADL。如果您发布版本 1 的库具有一个定义,class foo但版本 2 具有不同的定义,那么这两个库将不兼容!这就是重点。

但是,如果我不正确并且您确实想在您的 C++ 库中强制执行 C++ 名称修改(这很奇怪,因为它应该默认完成),那么答案是双重的。首先,看一些相关的问题:

阅读是相关的,但不是因果的。相关问题正在反向回答您的问题。

许多操作系统是用 C 语言编写的,这通常是您extern "C"在包含系统头文件时看到的原因。这也是为什么当您尝试使用在其库是用 C 而不是 C++ 编译的头文件中声明的内容时,有时会看到链接器抱怨缺少函数的原因。

所以朝着另一个方向(在你的方向):在你的头文件中,你可以将你的导出声明为extern "C++". 这告诉编译器在导入或导出对象时专门使用重整名称。

使用本身extern "C++"不会是你的魔术。有一些 GCC 选项可以控制一些关于名称修改的更具体的功能。所以,其次,看看那些。GCC 手册页的(外部链接)在这里:https ://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Dialect-Options.html

任何提及 ABI 的选项,例如-fabi,都可能会影响您。“ -fabi”标志与“应用程序二进制接口”相关。您可能还想了解有关这些术语的更多信息。什么是应用程序二进制接口有一些很好的答案来描述 ABI 是什么以及如何开始推理它们。" -Wabi" 将告诉 GCC 在检测到潜在的 ABI 冲突时发出警告。但是,就像所有的 C++ 一样,它也不是万无一失的。如果存在可能无法检测到的名称修改问题,我不会感到惊讶。如果您混合了异构编译器供应商或版本,则尤其如此。

重要的是:混合 ABI 可能会让人头疼。我会非常担心 ABI 不兼容被强制在一起并导致非常难以调试的未定义行为!


推荐阅读