これは、私のコメントをDavidの答えにさらに拡張するためのものです。
DLL側:
- DLLにInitプロシージャを追加します
- エクスポートします。
- 必要に応じて必要なtype/var宣言を追加します
スニペットコード:
library TheDLL;
...
var
OwnerAPP: HMODULE; // To be initialized by a call of the exported procedure Init from the EXE
...
type
TTestCallfromExe = procedure(f_Text: PAnsiChar); stdcall;
var
OwnerAPP: LongInt;
l_TestCallfromExe: TTestCallfromExe;
procedure Init(Owner: HMODULE);
begin
OwnerAPP := Owner;
end;
...
exports
Init, // This is it and the others exports follow
...
TestCallfromExeの呼び出しは、DLLのエクスポートされた関数/プロシージャへの通常の呼び出しと同じように実行されます。OwnerAPPが正しく初期化されている限り、OPの要件に従って、DLLのエクスポートされた関数の本体で呼び出しを行うことができます。
EXE側:
必要に応じて、すべてのプロシージャ/関数(DLLから呼び出される)をエクスポートします。もちろん、それぞれを実装する必要があります。
program TheEXE;
uses
...
MyExportImplementation; // Refence to implementatio unit
...
exports
TestCallfromExe, // This is it
...
begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
実装の詳細の例:
unit MyExportImplementation;
interface
...
procedure TestCallfromExe(f_Text: PAnsiChar); stdcall;
implementation
...
procedure TestCallfromExe(f_Text: PAnsiChar); stdcall;
begin
MessageBoxA(0, f_Text, 'Exe Dialog Ansi (stdcall)', 0);
end;
...
end.
すべてを一緒に入れて:
これは、DemoDLL(BTMemoryから)サンプルに基づいており、たとえば、TheEXE.dprプロジェクトのMainFormユニットに実装されます。
procedure TForm1.BtnCAllClick(Sender: TObject);
var
l_Init: procedure(Owner: HMODULE);
begin
m_DllHandle := LoadLibrary('TheDLL.dll');
try
if m_DllHandle = 0 then
Abort;
@l_Init := GetProcAddress(m_DllHandle, 'Init'); // <<<
if @l_Init = nil then
Abort;
// Fetch the remainding exported function(s)/procedure(s) adresses
l_Init(HInstance); // <<< Hand EXE's HInstance over to the DLL
// Call exported function(s)/procedure(s) accordingly
except
Showmessage('An error occured while loading the dll');
end;
if m_DllHandle <> 0 then
FreeLibrary(m_DllHandle)
end;
Nota Bene:
BTMemoryでもテストしましたが、動作します。