跨DLL边界传递C++类的可行方案与相关疑问
跨C++ DLL边界的ABI不一致问题分析
场景归纳
场景1:跨DLL边界传递的类完全一致,此情况可行
此场景下,DLL与可执行文件中Foo类的定义完全相同,包括成员变量布局、成员函数签名与实现逻辑,跨边界传递对象或引用不会出现问题。
场景2:跨DLL边界传递的类存在差异,不建议这么做
当DLL与可执行文件中的Foo类定义不一致时(比如成员变量顺序/大小不同、成员函数签名或实现有差异),直接跨边界传递该类对象或引用会触发未定义行为,例如内存访问错误、逻辑混乱等。
场景3:传递的数据为C原生类型,此情况仍可行
C原生类型(如int、char*、float等)的内存布局和调用约定在同一平台下是稳定统一的,即使存在ABI不一致的情况,跨DLL边界传递这类数据依然安全可靠。
讨论
我认为上述归纳是正确的,若有错误欢迎指正。
针对场景2,我有以下疑问:
- 是否可以在可执行文件中填充来自DLL的
Foo对象? - 使用原始类的话,除了巧合之外,这种操作是否永远无法生效?
举个例子,假设DLL中有供客户端调用的函数:
void getFoo(Foo& clientsFoo){ // 仍然无法生效,因为客户端的setValue函数与DLL版本的setValue可能不匹配 clientsFoo.setValue(myFoo.member1); }
那么实际开发中常用的解决方法是不是对要填充的类进行抽象?
比如采用共享虚接口的方式:
class IFoo{ public: virtual ~IFoo() = 0; virtual void setValue(const char* name) = 0; }; IFoo::~IFoo(){}
随后将DLL中的函数修改为:
void getFoo(IFoo& clientsFoo){ // 现在可以正常生效,因为会调用客户端实现的setValue逻辑 clientsFoo.setValue(myFoo.member1); }
不过我猜测这种方式仅在接口的函数仅接收/返回原生类型时才可行?
内容的提问来源于stack exchange,提问作者Natio2
相关产品推荐
相关产品推荐

