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 意思是 obj1obj2 都是从同一个 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::functake the address,这是一个相对地址,并且对于两个 classes 都是相同的。

由于您的构造处于 ODR 的极限并建立在特定于实现的行为之上,我认为安全区分您的 classes 的最简单方法是提供一个主页-在 foo 中创建了虚拟类型识别功能,例如将 class 和 dll 名称组合在一起。