库中所有符号的显式名称修饰(也称为名称修饰)

时间:2019-07-16 14:06:39

标签: c++ c linux shared-libraries static-libraries

在用c(或cpp)编写的库中是否有任何方法可以显式地进行名称修饰(也称为名称修饰)。我希望共享库中的所有符号都可以修饰其名称。

考虑以下问题: Two library of different versions in an application 在这种情况下,如果我可以明确地修改它们的所有名称,我想我可以解决这个问题。也许gcc编译器本身有一些选择可以做到这一点。

1 个答案:

答案 0 :(得分:1)

您的问题是:

  

在用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”标志与“应用程序二进制接口”有关。您可能还想了解更多有关这些术语的信息。 What is an application binary interface有一些出色的答案,它们描述了什么是ABI以及如何开始对此进行推理。当检测到潜在的ABI冲突时,“ -Wabi”将通知GCC发出警告。但是,就像所有C ++一样,它也不是万无一失的。如果存在可能无法检测到的名称更改问题,我不会感到惊讶。如果您混合使用各种编译器供应商或版本,则尤其如此。

重要的是:混合ABI可能会引起很大的麻烦。我会非常担心ABI的不兼容性被强加在一起并导致非常难以调试的未定义行为!