具有回调过程的动态DLL-Delphi

时间:2019-09-03 02:13:08

标签: delphi dll

我想动态加载DLL函数。 此函数在静态DLL模式下运行良好。但是我无法管理它在动态模式下工作。

type
  TCallBackProcedure = procedure(StringValue: PAnsiChar;
    IntegerValue: integer)stdcall;

type
  TOpenPort = function(dnum: integer;
    CallBackString: TCallBackProcedure): integer;


function xOpenPort(dnum: integer; CallBackString: TCallBackProcedure): integer;

const

  tDLL = 'myDll.dll';

function OpenPort(dnum: integer; CallBackString: TCallBackProcedure): integer;
  stdcall; external tDLL;

procedure CallBackString(StringValue: PAnsiChar; integerValue : Integer) stdcall;
begin
  strAA := StringValue; // string
  SLb.Add(strAA); // StringList
end;

以静态模式运行没有问题。

 iOutput := OpenPort(9, @CallBackString); // working fine

这是我在动态负载下调用它的努力;

function xOpenPort(dnum: integer; CallBackString: TCallBackProcedure): integer;
var
  hDll: THandle;
  xOpen: TOpenPort;
begin
  try
    hDll := loadLibrary(tDLL);
    if hDll <> 0 then
    begin
    //load dll OK 
      @xOpen := getProcAddress(hDll, 'OpenPort');
      if @xOpen <> nil then
      begin
        Result := 5;
      // I see also function is loaded
        Result := xOpen(dnum, @CallBackString);  
        prn(IntToStr(Result));
      end;
    end;
  finally
    freeLibrary(hDll);
  end;
end;

我怎么称呼:

iOutput := xOpenPort(9, @CallBackString);  // access violation

我遇到访问冲突。如何在动态加载中调用任何这样的DLL?在静态模式下,我有很多这样的功能。

1 个答案:

答案 0 :(得分:5)

您对TOpenPort类型的定义缺少stdcall调用约定,就像您对OpenPort()的静态定义使用的是:

type
  TOpenPort = function(dnum: integer; CallBackString: TCallBackProcedure): integer; stdcall; 

没有该调用约定,而是使用Delphi的默认register调用约定,从而导致参数值通过CPU寄存器传递,而不是通过DLL函数希望在其中找到它们的调用堆栈传递。

此外,在xOpenPort()函数中,将@参数传递给CallBackString时不要使用xOpen运算符。参数已经是正确的类型。您需要传递其值(即回调函数的内存地址),而不是参数本身的内存地址,因此只需将其原样传递给xOpen

Result := xOpen(dnum, CallBackString);