我必须使用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参数的值。
任何人都可以提供解决此问题的指示。
答案 0 :(得分:3)
你确定stdcall惯例吗?如果C ++文本中没有明确的说明(如WINAPI,__ stdcall等),那么使用cdecl。
'const'
为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初始化为非空字符串(长度足够长)。