显示表单时,从C ++调用的Delphi DLL崩溃

时间:2011-02-06 15:59:22

标签: c++ delphi forms dll crash

编辑:愚蠢的问题,已经修复。 Form1nil,因为我没有为它分配一个新的TForm1,我忘了Delphi并不像C ++那样为你做这件事。

我有一个Delphi DLL,我想用于我的C ++程序的GUI,所以对于初学者,我创建了一个表单,并且有一个函数将显示导出的表单,以便C ++可以调用它。但是,程序在调用函数时崩溃。这是我的代码。 (我正在使用Delphi 2010)

delphi部分:

unit Main;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Tabs, ComCtrls;

type
  TForm1 = class(TForm)
    TabControl1: TTabControl;
    TabSet1: TTabSet;
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

function ShowForm(i: Integer) : Integer; export; cdecl;

exports
  ShowForm name 'ShowForm';

implementation

{$R *.dfm}

function ShowForm(i: Integer) : Integer; export; cdecl;
begin
  Form1.Show();

  Result := 3; // random value, doesn't mean anything
end;

end.

这是C ++代码:

HMODULE h = LoadLibrary("delphidll.dll");

if (!h) {
    printf("Failed LoadLibrary (GetLastError: %i)\n", GetLastError());

    return 0;
}

FARPROC p = GetProcAddress(h, "ShowForm");

if (p)
    printf("Found it @ %p\n", p);
else
    printf("Didn't find it\n");

((int(__cdecl *)(int))p)(34);

system("PAUSE");

return 0;

程序打印“Found it @”然后崩溃。如果我在Delphi DLL中注释Form1.Show(),它不会崩溃,并且函数返回3(由printf测试)。我错过了一些初始化或什么?感谢。

1 个答案:

答案 0 :(得分:2)

它失败的原因是var Form1: TForm1;未初始化。

var Form1: TForm1;未初始化的原因很可能是因为您将unit Main放入DLL项目中,但最初来自Delphi VCL项目Form1在自动创建列表中。

自动创建列表意味着Delphi .dpr将初始化表单。

现在您需要手动创建表单,因此您需要从DLL中导出这3个新例程,并让C ++ DLL调用它们:

function CreateForm() : Integer; export; cdecl;
begin
  try
    Application.CreateForm(TForm1, Form1);
    Result := 0;
  except
    Result := -1;
  end;
end;

function DestroyForm() : Integer; export; cdecl;
begin
  try
    if Assigned(Form1) then
    begin
      FreeAndNil(Form1);
      Application.ProcessMessages();
    end;
    Result := 0;
  except
    Result := -1;
  end;
end;

function DestroyApplication() : Integer; export; cdecl;
begin
  try
    FreeAndNil(Application);
    Result := 0;
  except
    Result := -1;
  end;
end;

此外,您应该在try...except函数实现的实现周围添加ShowForm块,作为exceptions and other language dependent run-time features should not cross DLL boundaries

你可能也应该做同样的事情来释放其他可能分配的动态内存。

- 的Jeroen