【问题标题】:Crash when C++ program calls Delphi DLL functionC++程序调用Delphi DLL函数时崩溃
【发布时间】:2010-12-12 04:16:13
【问题描述】:

我在 C++ 程序中有一个抽象类,看起来像

class Interface {
    virtual void blah() = 0;
    virtual int  asdf() = 0;
};

并且该 C++ 程序允许您使用 LoadLibrary 加载 DLL。加载 DLL 时,它使用 GetProcAddress 调用 DLL 中称为 Setup 的函数,并将指向 Interface 子类的指针作为参数传递。

我有一个 Delphi DLL 模仿该类并像这样公开 Setup 函数:

type 
Interface = class abstract
    procedure blah(); virtual; abstract;
    function asdf() : Integer; virtual; abstract;
end;

function Setup(I : Interface) : Integer; export; cdecl;
begin
    Result := 0;
end

exports Setup;

但是当程序调用该函数时,它就崩溃了。如果我将功能设置更改为:

function Setup(I : Pointer) : Integer; export; cdecl;

它工作正常并且不会崩溃,但我当然不能就这样离开它,我需要能够使用该类。谁能告诉我我做错了什么?

【问题讨论】:

  • 我不知道如何解决您的问题,因为我不太使用(也不关心?)调用约定。但我要说的是,看起来你在修改你的调用约定方面走在了正确的轨道上。您可能想为您的 C++ 接口更改它。
  • 我无法控制 C++ 代码,只有 delphi。
  • 您真的完全无法控制 C++ 代码吗?你甚至不能向 C++ 开发人员抱怨他们搞砸了,然后要求他们修复它?这不好。

标签: c++ delphi function dll crash


【解决方案1】:

我不了解 C++,但 Delphi 接口会自动进行引用计数(通过 IUnknown)。看起来你的界面在你尝试使用它时已经被破坏了。

编辑: 抱歉,我很困惑:你没有使用接口。

Delphi 和 C++ 类不兼容,所以我认为这行不通。您必须将类更改为 COM 接口或函数指针记录。如果你无法控制 C++ 方面,恐怕你就不走运了。

【讨论】:

    【解决方案2】:

    如果您的 C++ 代码确实如您所说,您需要确定它使用的调用约定。它肯定使用C调用约定吗?它是用什么编译的,调用约定的标志是什么?

    您的 Interface 类也需要包含调用约定,例如:

    Interface = class abstract
      procedure blah(); cdecl; virtual; abstract;
      function asdf() : Integer; cdecl; virtual; abstract;
    end;
    

    如果 C++ 使用的调用约定类似于 MSVC 的 fastcall,则在 Delphi 中没有直接的等价物。在这种情况下,您可以做的是在 MSVC 中编写一个代理 DLL,将接口从 MSVC fastcall 转换为 cdecl 或类似的。

    【讨论】:

    • 不,调用约定肯定是cdecl。只是为了确保我也尝试了 stdcall,它也崩溃了。
    • @john 你怎么能确定呢?仅仅因为 __stdcall 也崩溃并不足以做出这样的决定。您是否有权访问您尝试与之交互的 C++ 库的头文件?我会先看看它是如何原型化的。 Barry 的包装界面的建议可能是你最好的选择。
    • Microsoft C++ 类 使用 cdecl 作为它们的调用约定。他们使用 thiscall。这会将对象指针放在 ECX 寄存器中,并将声明的参数放在堆栈中。使用cdecl,指针将位于堆栈的顶部,这是Delphi 正在寻找它的地方。在 both 类上使用显式声明的调用约定。
    【解决方案3】:

    你可以看到http://rvelthuis.de/articles/articles-cppobjs.html

    但是是的,在 Delphi 中使用 C++ 并不是一件容易的事……而且不合适。

    【讨论】:

      猜你喜欢
      • 2018-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多