我想动态加载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?在静态模式下,我有很多这样的功能。
答案 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);