InBuff 很简单(我认为)。我通过了 TMemoryStream.Memory 和 TMemoryStream.Size。
是的。
问题是我如何在 DLL 中分配 OutBuff,调用者应用程序可以将其转换回 TMemoryStream 并随后释放该内存(由调用者应用程序)?
鉴于您展示的 DLL 函数的签名,您根本不会在 DLL 中分配内存。调用者必须分配它。调用者可以调用Process() 一次以获得所需的大小,然后分配它,然后再次调用Process() 来填充它。这样,调用者负责分配和释放内存。例如:
procedure Process(InBuff: Pointer; InBuffSize: Integer; OutBuff: Pointer; var OutBuffSize: Integer); stdcall;
begin
//...
if (OutBuf <> nil) then
begin
// copy no more than OutBuffSize bytes into OutBuf, and then
// update OutBuffSize with the number of bytes actually copied...
Move(..., OutBuf^, ...);
OutBuffSize := ...;
end else begin
// update OutBuffSize with the number of bytes needed for OutBuff...
OutBuffSize := ...;
end;
//...
end;
var
InStream: TMemoryStream;
OutStream: TMemoryStream;
BuffSize: Integer;
begin
InStream := TMemoryStream.Create;
try
// fill InStream as needed...
BuffSize := 0;
Process(InStream.Memory, InStream.Size, nil, BuffSize);
OutStream := TMemoryStream.Create;
try
OutStream.Size := BuffSize;
Process(InStream.Memory, InStream.Size, OutStream.Memory, BuffSize);
// use OutStream as needed...
finally
OutStream.Free;
end;
finally
InStream.Free;
end;
end;
如果您确实希望 DLL 分配内存,则必须更改 DLL 函数的签名以使 OutBuff 成为 var 参数。您还必须导出一个附加函数,以便 DLL 可以释放 DLL 分配的内存。这种方法的好处是调用者只需调用Process() 一次,DLL 可以决定它要如何分配和释放内存。例如:
procedure Process(InBuff: Pointer; InBuffSize: Integer; var OutBuff: Pointer; var OutBuffSize: Integer); stdcall;
begin
//...
OutBuffSize := ...;
GetMem(OutBuf, OutBuffSize);
Move(..., OutBuf^, OutBuffSize);
//...
end;
procedure FreeProcessBuff(InBuff: Pointer); stdcall;
begin
FreeMem(InBuff);
end;
type
TMemoryBufferStream = class(TCustomMemoryStream)
public
constructor Create(APtr: Pointer; ASize: NativeInt);
end;
procedure TMemoryBufferStream.Create(APtr: Pointer; ASize: NativeInt);
begin
inherited Create;
SetPointer(APtr, ASize);
end;
...
var
InStream: TMemoryStream;
OutStream: TMemoryBufferStream;
Buff: Pointer;
BuffSize: Integer;
begin
InStream := TMemoryStream.Create;
try
// fill InStream as needed...
Buff := nil;
BuffSize := 0;
Process(InStream.Memory, InStream.Size, Buff, BuffSize);
try
OutStream := TMemoryBufferStream.Create(Buff, BuffSize);
try
// use OutStream as needed...
finally
OutStream.Free;
end;
finally
FreeProcessBuff(Buff);
end;
finally
InStream.Free;
end;
end;