You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

向DLL传递对象指针:Editor.exe与game.dll交互问题咨询

问题分析与解决方案

这种跨模块传递类指针的问题我碰到过好多次,核心原因基本都是模块间的类布局或ABI不兼容,咱们一步步拆解问题和解决办法:

最可能的问题根源

  • Core类内存布局不一致:Editor.exe和game.dll是独立编译的,如果两边使用的core.h有差异(比如类成员顺序/数量不同、条件编译导致的结构变化),或者编译选项(比如内存对齐、Debug/Release模式、C++标准)不一致,DLL里对Core对象的内存访问就会直接出错。
  • ABI兼容性冲突:不同编译器版本、不同CRT(C运行时库)链接方式,或者函数调用约定不匹配,都会导致函数调用时的参数传递、栈处理出错。
  • 虚函数表不匹配:如果Core包含虚函数,两边编译生成的虚表顺序不一致,DLL调用虚函数时就会跳转到错误的地址。

针对性解决办法

1. 强制Core类定义与编译选项完全统一

  • 确保Editor和game.dll使用完全相同的core.h头文件,头文件里不能有任何会改变类结构的条件编译(比如#ifdef _DEBUG添加额外成员)。
  • 统一所有编译选项:
    • 内存对齐选项(比如VS的/Zp参数)必须一致;
    • 统一使用Debug或Release模式,混合模式大概率出问题;
    • 统一C标准版本(比如都是C17);
    • 统一CRT链接方式:如果Core里用到了STL容器(比如std::string),必须都用动态链接CRT(/MD或/MDd),避免跨模块内存分配/释放崩溃。

2. 改用接口隔离(推荐方案)

直接传递具体类指针很容易踩ABI的坑,最好用纯虚基类作为接口,让Core继承这个接口,DLL只依赖接口定义:

// core.h - 两边共用的接口定义
class ICore {
public:
    virtual void requiredMethod() = 0;
    virtual int getValue() const = 0;
    virtual ~ICore() = default; // 必须声明虚析构,避免内存泄漏
};

// Editor.exe中的Core实现
class Core : public ICore {
private:
    int internalValue;
public:
    void requiredMethod() override { /* 具体实现 */ }
    int getValue() const override { return internalValue; }
};

// game.dll中的gameInit声明与实现
extern "C" __declspec(dllexport) void gameInit(ICore* core) {
    // 只通过ICore接口调用方法,不直接访问Core的私有成员
    core->requiredMethod();
}

// Editor.exe中调用代码调整为
gameInitFuncPtr init = (gameInitFuncPtr)GetProcAddress(LoadLibraryA("game.dll"), "gameInit");
init(static_cast<ICore*>(&core));

这种方式只要接口不变,Core的内部实现怎么改都不会影响DLL,从根源避免了布局不兼容的问题。

3. 确保函数调用约定匹配

GetProcAddress获取的函数默认是C调用约定(__cdecl),一定要保证gameInit的声明在两边完全一致:

// core.h中明确声明调用约定
extern "C" __declspec(dllexport) void __cdecl gameInit(Core* core);

如果用了__stdcall,类型转换时也要对应上,否则会导致栈损坏。

内容的提问来源于stack exchange,提问作者marciovmf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 04:02:20