在某些时候,您可能需要在运行时加载库(并使用其函数);当您为程序编写某种插件或模块架构时,这种情况最常发生。
在 C 语言中,加载库非常简单(调用dlopen, dlsym和dlclose就足够了),对于 C++ 来说,这有点复杂。动态加载 C++ 库的困难部分是由于名称修饰,部分是由于事实上dlopenAPI 是以 C 语言为思路编写的,因此没有提供加载类的合适方法。
在解释如何在 C++ 中加载库之前,让我们通过更详细地了解名称修饰来更好地分析问题。我建议您阅读名称修饰的解释,即使您对此不感兴趣,因为它将帮助您理解为什么会发生问题以及如何解决问题。
在每个 C++ 程序(或库,或目标文件)中,所有非静态函数都以符号的形式在二进制文件中表示。这些符号是特殊的文本字符串,用于唯一标识程序、库或目标文件中的函数。
在 C 语言中,符号名称与函数名称相同:strcpy的符号将是strcpystrcpy
等等。这是可能的,因为在 C 语言中,没有两个非静态函数可以具有相同的名称。因为 C++ 允许重载(具有相同名称但参数不同的不同函数)并且具有许多 C 语言没有的功能——例如类、成员函数、异常规范——所以不可能简单地使用函数名称作为符号名称。为了解决这个问题,C++ 使用所谓的名称修饰,它将函数名称和所有必要的信息(例如参数的数量和大小)转换为一些看起来很奇怪的字符串,只有编译器知道。例如,foo的修饰名称可能看起来像foo@4%6^
,例如。或者它甚至可能不包含 "foo" 这个词。dlsym名称修饰的问题之一是 C++ 标准(目前 [ISO14882])没有定义名称必须如何修饰;因此,每个编译器都以自己的方式修饰名称。一些编译器甚至在不同版本之间更改其名称修饰算法(特别是 g++ 2.x 和 3.x)。即使您弄清楚了您的特定编译器如何修饰名称(因此能够通过