如何在Delphi 11开发的DLL中调用主应用程序的过程
实现DLL调用主应用程序过程的Delphi 11示例
核心思路是主应用程序将自身过程的地址传递给DLL,DLL通过保存的地址调用主程序的过程。下面是具体实现步骤:
1. 定义共享的过程类型
新建一个公共单元(比如SharedTypes.pas),主程序和DLL都要引用这个单元,用来定义和主程序过程匹配的函数类型:
unit SharedTypes; interface type TDrawRectangleProc = procedure(X, Y, W, H: Integer); stdcall; // 调用约定要和主程序保持一致 implementation end.
2. 主应用程序端实现
主程序的目标过程实现
保留你原有的过程逻辑,补充调用约定声明:
procedure DrawRectangle(X, Y, W, H: Integer); stdcall; var MyRect: TRectangle; begin MyRect := TRectangle.Create(MainForm); MyRect.Position.X := X; MyRect.Position.Y := Y; MyRect.Width := W; MyRect.Height := H; MyRect.Parent := MainForm; // 其他绘制逻辑... end;
主程序加载DLL并传递过程地址
主程序需要加载DLL,然后调用DLL导出的注册函数,把DrawRectangle的地址传递给DLL:
var DLLHandle: THandle; // 全局变量,用于后续释放DLL procedure TMainForm.FormCreate(Sender: TObject); type TRegisterDrawProc = procedure(DrawProc: TDrawRectangleProc); stdcall; var RegisterDrawProc: TRegisterDrawProc; begin DLLHandle := LoadLibrary('YourDLL.dll'); // 替换为你的DLL文件名 if DLLHandle <> 0 then begin @RegisterDrawProc := GetProcAddress(DLLHandle, 'RegisterDrawRectangle'); if Assigned(RegisterDrawProc) then begin RegisterDrawProc(DrawRectangle); // 将主程序过程地址传给DLL end; end; end; procedure TMainForm.FormDestroy(Sender: TObject); begin if DLLHandle <> 0 then FreeLibrary(DLLHandle); end;
3. DLL端实现
DLL保存主程序过程地址并实现调用逻辑
DLL需要导出注册函数来接收主程序传递的地址,之后就可以在内部调用该过程:
library YourDLL; uses SysUtils, Classes, SharedTypes; {$R *.res} var FDrawRectangle: TDrawRectangleProc; // 保存主程序过程的地址 // 导出给主程序调用的注册函数 procedure RegisterDrawRectangle(DrawProc: TDrawRectangleProc); stdcall; begin FDrawRectangle := DrawProc; end; // DLL内部调用主程序过程的示例(也可导出该函数,让主程序主动触发调用) procedure CallMainDrawLogic; stdcall; begin if Assigned(FDrawRectangle) then FDrawRectangle(10, 10, 100, 100); // 调用主程序的DrawRectangle end; exports RegisterDrawRectangle, CallMainDrawLogic; // 可选导出,供主程序触发调用 begin FDrawRectangle := nil; end.
关键注意事项
- 必须保证调用约定完全一致(示例中统一用
stdcall),否则会引发栈溢出或内存错误。 - 公共单元的函数类型定义,参数数量、类型、顺序必须和主程序过程完全匹配。
- 主程序要确保在DLL完成所有调用后再释放DLL,避免出现无效地址访问。
内容的提问来源于stack exchange,提问作者Mick
相关产品推荐
相关产品推荐

