Delphi:为什么我可以静态链接该函数但不能动态链接?

标签 delphi dll dynamic access-violation

我目前正在编写一个模块,该模块与支票扫描仪的黑盒第 3 方 DLL 接口(interface)。我需要动态加载 DLL 函数,这适用于除一个函数之外的所有函数。
SetScanParameters 函数有一个记录结构作为参数,我认为这在某种程度上干扰了我用来动态加载它的方法(见下文)。动态加载时,该函数会因访问冲突而中断。
然而,SetScanParameters 在静态加载时确实会加载并正常运行。 我还需要做其他事情来动态加载具有记录结构的函数吗?

为了清晰起见,自行编辑:

记录类型:

  TBK_ScanParameter=packed record
    Left:short;
    Top:short;
    Width:short;
    Length:short;
    //
    xResolution:short;
    yResolution:short;
    BitsPerPixel:short;
    LightControl:short;
    MotorControl:short;
    //
    rGain:short;
    gGain:short;
    bGain:short;
    rOffset:short;
    gOffset:short;
    bOffset:short;
    rExposure:short;
    gExposure:short;
    bExposure:short;
    //
    FeedDirection:short;
    CropImage:short;
    ScanWithMICR:short;
    //
    Reserved:array [0..14] of short;
  end;

静态声明:

function BK_SetScanParameter(var ScanParameter:TBK_ScanParameter):integer; cdecl;

静态实现:

function BK_SetScanParameter(var ScanParameter:TBK_ScanParameter):integer; cdecl; external 'BKV2.dll' name '_BK_SetScanParameter@4';

动态逻辑(或者如果我不必使用静态调用来使其工作,那么什么是动态逻辑):

function TdmScannerV2.SetScanParameter(pScanParameter: TBK_ScanParameter): string;
type
  TBK_SetScanParameter = function (var ScanParameter:TBK_ScanParameter):integer; stdcall;
var
  hV2Dll:HMODULE;
  func:TBK_SetScanParameter;
begin
  hV2Dll:=0;
  result := '';
  try
    hV2Dll:=LoadLibrary('BKV2.dll');
    if hV2Dll>0 then
    begin
      @func:=GetProcAddress(hV2Dll, '_BK_SetScanParameter@4');
      if Assigned(@func) then
      begin
        try
          if BK_SetScanParameter(pScanParameter) > 0 then  {This one works, but is static}
          //if func(pScanParameter) > 0 then  {this one gets an AV}
          begin
            Result := 'Y:Scan Parameters Set';
          end
          else
            Result := 'ERROR:Failure code returned';
          {
          if func(pScanParameter) > 0 then
            Result := 'Y:Scan Parameters Set'
          else
            Result := 'ERROR:Failure code returned';
          }
        except
          on e:Exception do
          begin
            Result := 'ERROR:Exception:' + e.Message;
          end;
        end;
      end
      else
        Result := 'ERROR:Unable to load BK_SetScanParameter';
    end
    else
      Result := 'ERROR:Unable to load BKV2.dll';
  finally
    if hV2Dll>0 then FreeLibrary(hV2Dll);
  end;
end;

我尝试过在动态上使用 stdcall、cdecl、safecall、pascal 和 register,它们都生成了 AV。我还尝试在结构 [1..15] 而不是 [0..14] 中创建数组。并且在 但我不明白的是,如果我将结构传递到静态版本中,它就会起作用。

此外,OP 中存在一些拼写错误,对此我深表歉意。我正在重写OP中的代码并犯了一些拼写错误,这可能使线程有点困惑。我已将其替换为当前测试函数的复制/粘贴。

编辑:下面是 DLL 文档中描述的 typedef:

typedef struct ScanParameter
{
    short Left;            // left start positsion
    short Top;             // top start positsion
    short Width;           // scan image width in 1/100 inch
    short Length;          // scan image length in 1/100 inch

    short xResolution;     // horizontal resolution
    short yResolution;     // vertical resolution
    short BitsPerPixel;    // 24bit color, 8bit gray
    short LightControl;    // 0 - All lamp Off, 1 - red, 2 - green, 3 - blue, 4 - All lamp On
    short MotorControl;    // Motor Control, 0 - off, 1 = on

    short rGain;         // AFE R-Gain
    short gGain;         // AFE G-Gain
    short bGain;         // AFE B-Gain
    short rOffset;       // AFE R-Offset
    short gOffset;       // AFE G-Offset
    short bOffset;       // AFE B-Offset
    short rExposure;         // AFE R-Exposure
    short gExposure;         // AFE G-Exposure
    short bExposure;         // AFE B-Exposure

    short FeedDirection;   // feedout paper direction, 0 –fordward, 1 - backward
    short CropImage;       // 0 - no trim edge , 1 - trim edge
    short ScanWithMICR;    // 0 –off, 1 –scan image until paper leave device

    short Reserved[15];
} ScanParameter;

最佳答案

如上所述,调用约定看起来应该是 cdecl,而不是 stdcall。其次,尝试将加载库更改为,

hV2Dll := LoadLibrary('Scan.dll');

原件有“ScanDLL.dll”。

关于Delphi:为什么我可以静态链接该函数但不能动态链接?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1883997/

相关文章:

MySQL 动态 ORDER BY

c# - 创建动态对象

linux - 如何使用shell脚本访问linux中的特定路径

c++ - 如何在函数返回之前将新大小的数组从 C++ DLL 发送到 Delphi

delphi - 如何实现Delphi的ToolsAPI的IOTAProjectCompileNotifier?

delphi - 如何使用引用泛型类型的复杂类型

c# - 为什么不能使用 "copy local"将 .NET dll 包含在应用程序中 - 这样就不需要安装的 .NET

java - 可运行的 JavaCV 项目

Delphi Now() 函数返回错误值

c++ - 如何包装作为成员函数的 DLL 函数?