動的DLL呼び出しで、コールバック関数を送るには?

解決


bob  2005-02-05 22:16:09  No: 13046

(たぶん)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プロジェクト)


.  2005-02-06 03:18:39  No: 13047

dllInit(@dllCallBack, @Memo1, 0, @ErrCode);    //この行でエラー
Memo1のぽいんたのせいじゃないの


bob  2005-02-07 00:51:27  No: 13048

dllInit(@dllCallBack, nil, 0, @ErrCode);    //この行でエラー
でもだめなんです。


bob  2005-02-07 02:59:16  No: 13049

自己解決しました。
よく考えたら(ほぼ)当たり前の事ですが、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);
にすべきでした。ありがとうございます。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加