2011-02-06 69 views
1

编辑:哑问题,已经修复。 Form1nil,因为我没有为它指定一个新的TForm1,我忘记了Delphi不会为你像C++那样做。从C++调用的Delphi DLL在显示表单时崩溃

我有一个Delphi DLL,我想用于我的C++程序的GUI,因此只是为了初学者,我创建了一个窗体,并且有一个函数将显示导出的窗体,以便C++可以调用它。但是,程序在调用该函数时会崩溃。这是我的代码。 (我使用德尔福2010)

德尔福部分:

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; 

该程序打印 “找到它@”,然后崩溃。如果我在Delphi DLL中注释掉Form1.Show(),它不会崩溃,并且函数返回3(由printf测试)。我是否缺少一些初始化或某些东西?谢谢。

+0

@David我不知道该怎么做。 – Okey 2011-02-06 18:49:02

回答

2

它激怒的原因是var Form1: TForm1;未被初始化。

的原因,var Form1: TForm1;没有初始化,很可能是因为你把unit Main成DLL项目,但它最初是从一个Delphi VCL项目,您自动创建名单上有Form1来了。

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

现在你需要手动创建表单,所以你需要这3个新的程序从DLL导出,并有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

+0

Jeroen,很好的答案,但是OP已经达到了这个结论并编辑了Q! – 2011-02-06 17:00:03