2010-11-24 90 views
8

我有,我有一个返回PChar类型的函数DLL返回PChar类型。 (为避免使用borlndmm)我在做什么,原本是铸造一个字符串作为PChar类型并返回一个在Delphi中我的DLL我必须分配功能

Result := pChar(SomeFuncThatReturnsString) 

但我得到预期的结果90%的时间,其他时间我会回来没有。

然后我开始思考我需要为pchar分配内存,并且这样做我的原始方式是使用pchar指向内存,但当函数最初被调用时并不总是那样。所以,我现在有这个

Result := StrAlloc(128); 
Strcopy(Result,PAnsiChar(Hash(Hash(Code,1,128),2,128))); 

但是,这给我留下了不得不清理的节目结束我与

StrDispose(Pstr);  

做分配的内存,以使$ 64个问题是:我一定要分配从DLL里的函数返回一个PChar时的内存,还是我可以将它转换为PChar?

回答

7

的典型方法对这个问题是有应用程序分配内存,然后将它传递给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; 
5

DLL和你的主应用程序有两种不同的内存管理器,所以它是不正确的DLL中分配内存,但它免费在主应用程序,反之亦然。

您可以使用WideString类型从dll返回字符串或将它传递给dll - WideString是系统BSTR类型的包装,WideString变量的内存由系统内存管理器自动分配。

另一种解决方案是使用SimpleShareMem代替ShareMem(仅适用于Delphi 2007及更早版本) - 它的工作方式与ShareMem类似,但不需要任何borlnmm.dll类库来重新分发。

+1

这一块,对不对? http://edn.embarcadero.com/article/33416 – 2010-11-24 23:39:44

+0

是的,“ShareMemoryManager”部分。而且,我的错误,新的内存管理器可从2006年开始德尔福,而非2007年。 – 2010-11-25 13:54:43

1

当您返回一个字符串作为PChar类型从函数中将字符串保存在堆栈中,这就是为什么它有时会被损坏。我使用进程堆内存来返回字符串,或指向全局字符缓冲区数组的指针。

您也可以使用内置的汇编和做到这一点:

Function GetNameStr : PChar; 
Asm 
    Call @OverText 
    DB  'Some text',0 
@OverText: 
    Pop EAX 
End; 
相关问题