我有一个提供解码功能的DLL,如下所示:
function MyDecode (Source: PChar; SourceLen: Integer; var Dest: PChar; DestLen: Integer): Boolean; stdcall;
Run Code Online (Sandbox Code Playgroud)
HostApp调用"MyDecode",并转移到Source,SourceLen和Dest参数,DLL返回解码的Dest和DestLen.问题是:HostApp无法知道解码的Dest长度,因此不知道如何预先分配Dest的内存.
我知道可以将"MyDecode"分成两个函数:
function GetDecodeLen (Source: PChar; SourceLen: Integer): Integer; stdcall; // Return the Dest's length
function MyDecodeLen (Source: PChar; SourceLen: Integer; var Dest: PChar): Boolean; stdcall;
Run Code Online (Sandbox Code Playgroud)
但是,我的解码过程非常复杂,因此如果分成两个功能会影响效率.
有更好的解决方案吗?
是亚历山大,这可能是一个很好的解决方案.HostApp代码:
//...
MyDecode(....)
try
// Use or copy Dest data
finally
FreeDecodeResult(...)
end;
Run Code Online (Sandbox Code Playgroud)
DLL代码:
function MyDecode(...): Boolean;
begin
// time-consuming calculate
// Allocate memory
GetMem(Dest, Size);
// or New()?
// or HeapAlloc()?
end;
procedure FreeDecodeResult(Dest: PChar);
begin
FreeMem(Dest);
// or Dispose(Dest); ?
// or HeapFree(Dest); ?
end;
Run Code Online (Sandbox Code Playgroud)
也许我应该将Dest的类型改为Pointer.
哪个是更好的分配内存方法?GetMem/New,还是HeapAlloc?
您可以通过其他方式将"MyDecode"拆分为两个例程:
function MyDecode(Source: PChar; SourceLen: Integer; out Dest: PChar; out DestSize: Integer): Boolean; stdcall;
procedure FreeDecodeResult(Dest: PChar); stdcall;
Run Code Online (Sandbox Code Playgroud)
即 - 你在MyDecode中分配内存而不是要求调用者这样做.
您可以使用大多数Windows API使用的相同技术,也就是说,如果您的缓冲区不够大,该函数将返回所需缓冲区的大小.这样,您可以从调用函数中分配正确大小的缓冲区.
function MyDecode (Source: PChar; SourceLen: Integer; Dest: PChar; var Len: Integer): Boolean; stdcall;
procedure SomeProc;
var iSourceLen, iLenNeeded : Integer;
pSource, pDest : Pointer;
begin
MyDecode(pSource, iSourceLen, nil, iLenNeeded);
GetMem(pDest,iLenNeeded);
try
MyDecode(pSource, iSourceLen,pDest, iLenNeeded);
finally
FreeMem(pDest);
end;
end;
Run Code Online (Sandbox Code Playgroud)
编辑:正如mghie所建议的那样.由于参数是PCHAR,因此假设MyDecode返回的iLenNeeded将是windows API所需的TCHAR(大部分是?)标准的数量.
function SomeProc(sEncode : String) : string;
var iLenNeeded : Integer;
begin
MyDecode(PChar(sEncode), Length(sEncode), nil, iLenNeeded);
SetLength(Result, iLenNeeded); //if iLenNeeded include a null-terminating character, you can use (iLenNeeded - 1) instead
if not MyDecode(PChar(sEncode), Length(sEncode), PChar(Result), iLenNeeded) then
SetLength(Result, 0);
end;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1253 次 |
| 最近记录: |