[c++] 如何安全地将对象(尤其是STL对象)传入DLL或从DLL传递?



Answers

@computerfreaker写了一个很好的解释,为什么缺少ABI会阻止在一般情况下跨越DLL边界传递C ++对象,即使类型定义在用户控制下并且在两个程序中都使用完全相同的令牌序列。 (有两种情况可行:标准布局类和纯接口)

对于C ++标准中定义的对象类型(包括那些改编自标准模板库的对象类型),情况远非如此糟糕。 定义这些类型的标记在多个编译器中并不相同,因为C ++标准不提供完整的类型定义,只提供最低要求。 此外,这些类型定义中出现的标识符的名称查找不能解析相同的名称。 即使在存在C ++ ABI的系统上,尝试跨模块边界共享此类型也会导致由于违反One Definition Rule而导致的大量未定义行为。

这是Linux程序员不习惯处理的事情,因为g ++的libstdc ++是事实上的标准,几乎所有程序都使用它,因此满足了ODR。 clang的libc ++打破了这个假设,然后C ++ 11出现了几乎所有标准库类型的强制更改。

只是不要在模块之间共享标准库类型。 这是未定义的行为。

Question

如何将类对象(尤其是STL对象)传递给C ++ DLL或从C ++ DLL传递?

我的应用程序必须以DLL文件的形式与第三方插件交互,我无法控制这些插件构建的编译器。 我知道STL对象没有保证ABI,我担心我的应用程序会导致不稳定。




您不能安全地跨DLL边界传递STL对象,除非所有模块(.EXE和.DLL)都使用相同的C ++编译器版本和CRT的相同设置和风格构建,这是高度约束的,显然不是您的情况。

如果要从DLL公开面向对象的接口,则应该公开C ++纯接口(类似于COM所做的那样)。 考虑阅读关于CodeProject的这篇有趣的文章:

HowTo:从DLL导出C ++类

您可能还需要考虑在DLL边界公开纯C接口,然后在调用者站点构建C ++包装器。
这与Win32中的情况类似:Win32实现代码几乎是C ++,但许多Win32 API都暴露了纯C接口(还有公开COM接口的API)。 然后ATL / WTL和MFC用C ++类和对象包装这些纯C接口。






Related