我仍然没有吸收的东西。几乎所有的开发工作都涉及静态地生成和编译我的代码,而不使用链接动态库(dll或.so)。
在这种情况下,我理解编译器和链接器在逐步执行代码时如何解析符号。
但是,例如,在动态库中进行链接时,动态库是使用与主代码不同的编译器编译的,符号名称是否会有所不同?
例如,我在主代码中定义了一个名为RequiredData的结构,如下所示。想象一下,FuncFromDynamicLib()函数是一个单独的动态库的一部分,它将相同的结构RequiredData作为参数。这意味着在动态库中的某个地方,必须再次定义这个结构吗?如何在动态链接时解决这些结构相同的问题。如果数据成员不同怎么办?提前谢谢。
#include <iostream>
using namespace std;
struct RequiredData
{
string name;
int value1;
int value2;
};
int FuncFromDynamicLib(RequiredData);
int main()
{
RequiredData data;
data.name = "test";
data.value1 = 120;
data.value2 = 200;
FuncFromDynamicLib(data);
return 0;
}
//------------Imagine that this func is Part of dynamic library in another file--------------------
int FuncFromDynamicLib(RequiredData rd)
{
cout<<rd.name<<endl;
cout<<rd.value1<<endl;
cout<<rd.value2<<endl;
}
//------------------------------------------------------
答案 0 :(得分:5)
你是完全正确的,你通常不能混合你的工具。 “链接”的过程没有标准化或指定,因此通常你必须在整个过程中使用相同的工具链,或者实际上一部分不知道另一部分如何在目标代码中调用符号。
问题实际上更糟糕:它不仅仅是必须匹配的符号名称,还包括调用约定:如何传播函数参数,返回值,异常以及如何处理RTTI和动态强制转换。
所有这些因素总结在术语“应用程序二进制接口”,ABI简称。您描述的问题可以概括为“没有标准的ABI”。
有几个因素使情况变得不那么可怕:
对于C代码,每个主要平台都是事实上的标准ABI,其后是大多数工具。因此,C代码在实践中具有高度的可移植性和可互操作性。
对于C ++代码,ABI比C更复杂。但是,对于x86和x86-64这两个主要平台,Itanium ABI用于各种平台,至少创建一个有点互操作的环境。特别是,ABI对名称修改的规则(即如何将名称空间限定名称和函数重载集表示为扁平字符串)是众所周知的,并且具有广泛的工具支持。
对于C ++,还有一些特殊问题。将已编译的代码发送给客户是一回事,但另一个问题是,大多数C ++库代码都存在于头文件中,并且每次都会编译。所以问题不仅在于您可能正在使用不同的编译器,还有不同的库实现。类布局的内部细节变得相关,因为您不能仅仅访问供应商A的向量,就好像它是供应商B的向量一样。 GCC称这个“库ABI”。