c++ class 跨 dll 冲突
c++ class collision across dll
我有一个基本抽象 class (interface
),它在许多 DLL 之间共享以从它继承。每个 DLL 都有一个导出的工厂符号,它动态创建一个对象和 returns 它的指针。如果两个不同的 DLL 具有从同一抽象 class 继承的具有相同名称的 class 会发生什么情况?
class foo
{
public:
virtual void func()const=0;
};
Dll1
class bar: public foo
{
public:
virtual void func()const{
std::cout << "From Dll1" << std::endl;
}
};
Dll2
class bar: public foo
{
public:
virtual void func()const{
std::cout << "From Dll2" << std::endl;
}
};
主要
int main()
{
foo* obj1;
foo* obj2;
// load DLLs
// import factory
// call factory to initialize objects
obj1->func(); // output: "From Dll1"
obj2->func(); // output: "From Dll2"
return typeid(*obj1) == typeid(*obj2);
}
Returns true
意思是 obj1
和 obj2
都是从同一个 class 实例化的。以及typeid(*obj1).name()
和typeid(*obj2).name()
returns同名class bar
。如果不允许我自己控制 DLL,有什么方法可以使用 RTTI
区分这些对象? class 是否必须有一种机制来为这种情况提供其 UUID
?
P.S.
正如 IInspectable 所说,您可以将对象映射到它的工厂。但是如果接口允许复合对象呢? DLL 永远不会区分从不同模块返回的对象,因为它不知道工厂。这是我想使用 RTTI
.
的主要原因
首先,这种构造只有run time dynamically linking of your DLLs. If you would use load-time dynamic linking才有可能,链接器会识别导入库中的重复符号。所以我们不再使用标准 C++,而是使用特定于实现的行为:
HINSTANCE dll1Handle = LoadLibraryA("Test0410-1DLL1.dll");
HINSTANCE dll2Handle = LoadLibraryA("Test0410-1DLL2.dll");
fct f1, f2;
foo *obj1, *obj2;
if (dll1Handle == NULL || dll2Handle == NULL) {
cout << "Both DLL couldn't be uploaded!" << endl;
}
else {
f1 = (fct)GetProcAddress(dll1Handle, "myfactory");
f2 = (fct)GetProcAddress(dll2Handle, "myfactory");
if (f1 == NULL || f2 == NULL) {
cout << "Both factories couldn't be uploaded!" << endl;
}
else {
obj1 = f1();
obj2 = f2();
obj1->func();
obj2->func();
if (typeid(obj1) == typeid(obj2))
cout << "Same type"<<endl;
else cout << "Different type" << endl;
}
}
MSVC 生成的代码发现两者具有相同的类型。但没有什么能确保这种行为。
也很难使用虚函数的指针,因为,你不能取obj->func
的地址,你需要取foo::func
的take the address,这是一个相对地址,并且对于两个 classes 都是相同的。
由于您的构造处于 ODR 的极限并建立在特定于实现的行为之上,我认为安全区分您的 classes 的最简单方法是提供一个主页-在 foo
中创建了虚拟类型识别功能,例如将 class 和 dll 名称组合在一起。
我有一个基本抽象 class (interface
),它在许多 DLL 之间共享以从它继承。每个 DLL 都有一个导出的工厂符号,它动态创建一个对象和 returns 它的指针。如果两个不同的 DLL 具有从同一抽象 class 继承的具有相同名称的 class 会发生什么情况?
class foo
{
public:
virtual void func()const=0;
};
Dll1
class bar: public foo
{
public:
virtual void func()const{
std::cout << "From Dll1" << std::endl;
}
};
Dll2
class bar: public foo
{
public:
virtual void func()const{
std::cout << "From Dll2" << std::endl;
}
};
主要
int main()
{
foo* obj1;
foo* obj2;
// load DLLs
// import factory
// call factory to initialize objects
obj1->func(); // output: "From Dll1"
obj2->func(); // output: "From Dll2"
return typeid(*obj1) == typeid(*obj2);
}
Returns true
意思是 obj1
和 obj2
都是从同一个 class 实例化的。以及typeid(*obj1).name()
和typeid(*obj2).name()
returns同名class bar
。如果不允许我自己控制 DLL,有什么方法可以使用 RTTI
区分这些对象? class 是否必须有一种机制来为这种情况提供其 UUID
?
P.S.
正如 IInspectable 所说,您可以将对象映射到它的工厂。但是如果接口允许复合对象呢? DLL 永远不会区分从不同模块返回的对象,因为它不知道工厂。这是我想使用 RTTI
.
首先,这种构造只有run time dynamically linking of your DLLs. If you would use load-time dynamic linking才有可能,链接器会识别导入库中的重复符号。所以我们不再使用标准 C++,而是使用特定于实现的行为:
HINSTANCE dll1Handle = LoadLibraryA("Test0410-1DLL1.dll");
HINSTANCE dll2Handle = LoadLibraryA("Test0410-1DLL2.dll");
fct f1, f2;
foo *obj1, *obj2;
if (dll1Handle == NULL || dll2Handle == NULL) {
cout << "Both DLL couldn't be uploaded!" << endl;
}
else {
f1 = (fct)GetProcAddress(dll1Handle, "myfactory");
f2 = (fct)GetProcAddress(dll2Handle, "myfactory");
if (f1 == NULL || f2 == NULL) {
cout << "Both factories couldn't be uploaded!" << endl;
}
else {
obj1 = f1();
obj2 = f2();
obj1->func();
obj2->func();
if (typeid(obj1) == typeid(obj2))
cout << "Same type"<<endl;
else cout << "Different type" << endl;
}
}
MSVC 生成的代码发现两者具有相同的类型。但没有什么能确保这种行为。
也很难使用虚函数的指针,因为,你不能取obj->func
的地址,你需要取foo::func
的take the address,这是一个相对地址,并且对于两个 classes 都是相同的。
由于您的构造处于 ODR 的极限并建立在特定于实现的行为之上,我认为安全区分您的 classes 的最简单方法是提供一个主页-在 foo
中创建了虚拟类型识别功能,例如将 class 和 dll 名称组合在一起。