解决此问题的典型方法是让应用程序分配内存,然后将其传递给 DLL 进行填充(如果 DLL 允许应用程序查询它需要分配多少内存,这样它就不必过度-分配内存):
function GetAString(Buffer: PChar; BufLen: Integer): Integer; stdcall;
var
S: String;
begin
S := SomeFuncThatReturnsString;
Result := Min(BufLen, Length(S));
if (Buffer <> nil) and (Result > 0) then
Move(S[1], Buffer^, Result * SizeOf(Char));
end;
这允许应用程序决定何时以及如何分配内存(堆栈与堆、重用内存块等):
var
S: String;
begin
SetLength(S, 256);
SetLength(S, GetAString(PChar(S), 256));
...
end;
var
S: String;
begin
SetLength(S, GetAString(nil, 0));
if Length(S) > 0 then GetAString(PChar(S), Length(S));
...
end;
var
S: array[0..255] of Char;
Len: Integer;
begin
Len := GetAString(S, 256);
...
end;
如果这不适合您,那么您需要让 DLL 分配内存,将其返回给应用程序以供使用,然后让 DLL 导出一个附加函数,应用程序在完成后可以调用该函数以传递指针返回 DLL 进行释放:
function GetAString: PChar; stdcall;
var
S: String;
begin
S := SomeFuncThatReturnsString;
if S <> '' then
begin
Result := StrAlloc(Length(S)+1);
StrPCopy(Result, S);
end else
Result := nil;
end;
procedure FreeAString(AStr: PChar); stdcall;
begin
StrDispose(AStr);
end;
var
S: PChar;
begin
S := GetAString;
if S <> nil then
try
...
finally
FreeAString(S);
end;
end;