在Delphi 6中使用C ++ DLL

时间:2012-10-05 11:07:42

标签: c++ delphi winapi dll delphi-6

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

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

数据是输入值,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;

我在“ERROR”作为评论的行中收到访问冲突

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

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

3 个答案:

答案 0 :(得分:3)

  1. 你确定stdcall惯例吗?如果C ++文本中没有明确的说明(如WINAPI,__ stdcall等),那么使用cdecl。

  2. 在不需要数据之前
  3. 'const'

  4. 为StOutput分配内存

答案 1 :(得分:3)

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

第一次调用中,您将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,并且您显示的声明没有另外说明。您已在Pascal中将其声明为stdcall。他们应该匹配。

答案 2 :(得分:2)

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