(たぶん)VC++で書かれたDLLを動的にロードし、DLL内の関数に
コールバック関数を登録したいのですが、うまく行かないので
ご教授お願いします。
DLLのヘッダ
/*
* int CALLBACK fncCallBack(unsigned long dwReason, unsigned long wParam, unsigned long lParam, void *uParam, unsigned long *errCode)
*/
typedef int (CALLBACK *func_CallBack)(unsigned long, unsigned long, unsigned long, void *, unsigned long *);
typedef int (WINAPI *func_Init)(func_CallBack, void *, unsigned long, unsigned long *);
そこで、以下の通りのコードで試してみたのですが、特権命令違反が出てうまくいきません。
type
pLongword = ^Longword;
TCallBack = function (dwReason, wParam, lParam: longword; uParam: Pointer; errCode: plongword): Integer;
function dllCallBack(dwReason, wParam, lParam: longword; uParam: Pointer; errCode: plongword): Integer; stdcall;
implementation
procedure TForm1.Button1Click(Sender: TObject);
type
TDllInit = function(func_CallBack: TCallBack; Value: Pointer; Option, ErrCode: pLongword): integer;
var
hLibrary: THandle;
dllInit: TDllInit;
ErrCode: longword;
begin
Memo1.Text := '';
hLibrary := LoadLibrary('hoge.dll');
if hLibrary <> 0 then
begin
@dllInit := GetProcAddress(hLibrary, 'fncInit');
if @dllInit <> nil then
begin
try
dllInit(@dllCallBack, @Memo1, 0, @ErrCode); //この行でエラー
Memo1.Text := Memo1.Text + IntToStr(ErrCode);
except
on E: Exception do
begin
Memo1.Text := e.Message;
FreeLibrary(hLibrary);
exit;
end;
end;
end else begin
ShowMessage('関数がない');
end;
end else
begin
ShowMessage('NotDLL');
end;
end;
function dllCallBack(dwReason, wParam, lParam: longword;
uParam: Pointer; errCode: plongword): Integer; stdcall;
begin
result := 0;
if uParam = nil then exit;
TMemo(uParam).Text := 'コールバック!!';
end;
環境は以下の通りです。
OS:WinXP SP2
Delphi: Delphi 2005 Pro(Delphi for Win32プロジェクト)
dllInit(@dllCallBack, @Memo1, 0, @ErrCode); //この行でエラー
Memo1のぽいんたのせいじゃないの
dllInit(@dllCallBack, nil, 0, @ErrCode); //この行でエラー
でもだめなんです。
自己解決しました。
よく考えたら(ほぼ)当たり前の事ですが、DLLの関数を渡すのにstdcall規約を
指定していませんでした。
#コールバックの方ではちゃんと指定しているのに...
よって
TDllInit = function(func_CallBack: TCallBack; Value: Pointer; Option, ErrCode: pLongword): integer;
を
TDllInit = function(func_CallBack: TCallBack; Value: Pointer; Option, ErrCode: pLongword): integer; stdcall;
に直したらできました。
P.S.
.さんのおっしゃるとおり、クラスもポインタなんだから
dllInit(@dllCallBack, Memo1, 0, @ErrCode);
にすべきでした。ありがとうございます。
ツイート | ![]() |