2010-11-24 27 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; 
相關問題