首页 文章

在Delphi 6中使用C DLL

提问于
浏览
1

我必须在Delphi 6中使用来自外部C DLL的编码函数 . 以下是提供的声明:

long <Function Name> (char *Data, long &Apply, char *ReturnVal, long &Size)

Data是输入值,Apply是布尔值(默认值:FALSE),ReturnVal是DLL的返回值,Size是ReturnVal的长度 .

为了在Delphi 6中使用它,我编写了以下代码:

implementation
   const
     EncoderDLL = '<DLL NAME>';
     FunctionName = 'FUNCTION NAME';
   var
      _TEST : function(const Data : PChar; Apply : PInteger;stOutput : Pchar;
          iSize : PInteger) : integer; stdcall;
   .....
   .....
   var
     stInput,stOutput : string;
     iLength,i1,iResult : integer;
     hnd : THandle;
   begin
     iLength := 0;
     i1 := 0;
     stInput := Trim(edtInput.Text);
     hnd := SafeLoadLibrary(EncoderDLL);
     if hnd > 0 then
     begin
       @_TEST := GetProcAddress(hnd,FunctionName);
       if @_TEST <> nil then
       begin
         iResult := _TEST(PChar(stInput),@i1,PChar(StOutput),@iLength); // ERROR
       end;
     end;
     FreeLibrary(hnd);
  end;

我收到 Access Violation 在'ERROR'作为评论 .

如果我用 string 替换函数声明中的 PChar ,则访问冲突不会出现在同一行 . 在释放图书馆的同时 . 此外,正确填充iLength参数的值 .

任何人都可以提供解决此问题的指示 .

3 回答

  • 3
    • 你确定stdcall惯例吗?如果C文本中没有明确的说明(如WINAPI,__ stdcall等),则使用cdecl .

    在不需要数据之前

    • 'const'

    • 为StOutput分配内存

  • 2

    保持PChar,并在调用之前将StOutput初始化为非空字符串(足够长) .

  • 3

    我假设 ReturnVal 是输出参数(函数填充它) . 您应该在代码中为此字符串保留内存 . 但是你应该保留多少记忆?这些功能有一个共同的模式 . You call the function twice .

    first call 中,您将 ReturnVal 设置为 nil ,该函数在 Size 参数中填写所需的大小 .

    然后在 StOutput 缓冲区中保留那么多内存并再次调用该函数 . 这次你得到的结果 .

    iResult := _TEST(PChar(stInput),@i1,nil,@iLength); // First call
    SetLength( stOutput, iLength ); // reserve memory
    iResult := _TEST(PChar(stInput),@i1,PChar(stOutput),@iLength); // Second call
    

    请注意,此功能可能会也可能不会遵循此约定 . 但如果没有,那么实际上没有办法告诉你应该为输出参数保留多少内存 .

    需要注意的另一件事是调用约定 . C和C函数默认为 cdecl ,而've shown doesn' t的声明则另有说明 . 你已经在Pascal中声明它为 stdcall . 他们应该匹配 .

相关问题