2010-11-24 2 views
8

pchar를 반환하는 함수가있는 DLL이 있습니다.내 DLL에 델파이에서 함수의 반환 pchar를 할당해야합니까?

Result := pChar(SomeFuncThatReturnsString) 

하지만 예상지고되었다가 시간의 90 %를 결과와 다른 시간은 내가 돌아올 것이라고 나는 원래 일을 한 PChar는 같은 문자열을 캐스팅하고 반환 무엇 (borlndmm를 사용하는 것을 피하기 위해) 아무것도.

그런 다음 pchar에 메모리를 할당해야한다는 생각이 들었습니다. 원래의 방법으로는 pchar 포인트가 메모리에 저장되는 것이 었습니다. 원래는이 함수가 원래 호출되었을 때 항상 존재하지는 않았을 것입니다. 그래서 나는 지금이

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

을하지만이 그래서 $ (64) 질문은 내가

StrDispose(Pstr);  

와 함께 할 프로그램의 끝에 할당 된 메모리를 정리하는 데 나를 잎 : 나는 할당해야합니까 메모리를 사용하여 DLL 내부의 함수에서 PChar를 반환하거나 PChar로 캐스팅 할 수 있습니까?

답변

7

이 문제에 대한 일반적인 접근 방식은 메모리를 할당 한 다음 채우기 위해 DLL에 전달하는 것입니다 (DLL이 앱이 할당 할 메모리 양을 쿼리하도록 허용하는 경우 더 좋습니다). 지나치게 할당 메모리)에 있습니다 :이 경우

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; 

: 이것은 언제 어떻게 메모리를 할당하기로 결정 앱을 허용

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; 

(메모리 블록 등) 재사용, 힙 대 스택 당신을위한 옵션이 아니라면, DLL을 가지고 메모리를 할당해야합니다. 당신이 PChar는 같은 문자열을 반환하는 경우

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; 
+0

셧다운 기능을 드러내 기 때문에 Windows 3.1은 fdwReason = DLL_PROCESS_DETACH 일 때 DllMain의 모든 정리 작업을 수행합니다. –

+0

이것이 내 대답과 무슨 상관이 있습니까?게다가 DllMain()에서는 항상 정리가 가능하지는 않지만 DllMain() 내부에서 직접 수행 할 수없는 작업이 있습니다. –

+0

"WEP (Windows 종료 절차) 콜백 함수는 라이브러리가 언로드되기 전에 동적 연결 라이브러리 (DLL)에 대한 정리를 수행합니다." 당신이 제안한 그게 아니야? 다시 : 안전하지 않은 작업 - 예를 들어 주겠니? –

5

DLL과 기본 응용 프로그램에는 두 개의 다른 메모리 관리자가 있으므로 DLL에 메모리를 할당하고 주 응용 프로그램에서 메모리를 할당하거나 그 반대의 경우도 마찬가지입니다.

dll에서 문자열을 반환하거나 dll로 전달할 때 WideString 형식을 사용할 수 있습니다. - WideString은 시스템 BSTR 형식의 래퍼이며 WideString 변수의 메모리는 시스템 메모리 관리자가 자동으로 할당합니다.

다른 해결책은 ShareMem (Delphi 2007 및 이전 버전 만) 대신 SimpleShareMem을 사용하는 것입니다.이 방법은 ShareMem처럼 작동하지만 재분배하려면 borlnmm.dll과 같은 라이브러리가 필요하지 않습니다.

+1

이 하나? http://edn.embarcadero.com/article/33416 –

+0

예, "ShareMemoryManager"섹션. 그리고 내 실수는 새로운 메모리 관리자가 2007 년 델파이 2006에서 시작 가능합니다. –

1

을 : 사용을위한 응용 프로그램에 그 다음은 DLL 앱이 해방을 위해이 DLL로 다시 포인터를 통과 할 때 호출 할 수있는 추가 기능을 내보낼 수 있습니다 function에서 문자열은 스택에 저장되어 있기 때문에 때때로 손상됩니다. 문자열을 반환하기 위해 프로세스 힙 메모리를 사용하거나 문자의 전역 버퍼 배열을 가리키는 포인터를 사용합니다.

또한 어셈블러 내장에서 사용할 수있는이 수행 오른쪽

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