Function Test: PChar w bibliotece DLL

0

Potrzebuje odpowiedzi na jedno pytanie którego nie mogłem znaleźć na forum. Na tej stronie jest ładnie opisane jak tworzyć funkcje które zwracają PCHar. Przyjmujemy że funkcja jest w bibliotece DLL oto ona;

function foo:PChar;
var
  s:string;
begin
  s:='Ala ma kota';
  GetMem(result, Length(s));
end;

Należy pamietać aby na koniec użyć FreeMem aby zwolnić zasoby. Ale jak to zrobić? Wiem jak wykonać jakaś procedure przy zamykaniu dll ale nie wiem jak w takim przypadku użyć FreeMem?

procedure Koniec;
begin
  FreeMem(function foo:PChar);  //Jak to powinno być wykonane?
end; 
0

Znalazłem jedno rozwiązanie w Google:

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;

Teraz pytanie czy mogę tak zrobić w bibliotece

Library Test1

Var  Zmienna : PChar;  //Zmienna globalna

function Test: PChar;
var
  s : String;
begin
  s:='Ala ma kota';
  GetMem(Zmienna, Length(s));
  Result := Zmienna;
end;

procedure Koniec;  // Procedura wykonuje sie automatycznie przy zwalnianiu biblioteki z pamięci
begin
  FreeMem(Zmienna,Length(Zmienna));
end
0

GetMem(Zmienna, Length(s)); // przydzielasz pamięć
Result := Zmienna; // podmieniasz wskaźnik na przydzieloną pamięć na wewnętrzny bufor string'a

0

Miało być:

function Test: PChar;
var
  s : String;
begin
  s:='Ala ma kota';
  GetMem(Zmienna, Length(s));
  Zmienna := PChar(S);
  Result := Zmienna;

end;
0
function Test: PChar;
var
  s : String;
begin
  s:='Ala ma kota';
  GetMem(Result,Length(s)+1); // +1 - bardzo ważne
  StrCopy(Result,PChar(s)); 
end;
0
function Test: PChar;
var
  s : String;
begin
  s:='Ala ma kota';
  GetMem(Zmienna, Length(s)+1);  // Ostatni znak 0
  StrPCopy(Zmienna,PChar(S));
  Result := Zmienna;
end;

Rozumiem że StrPCopy(Zmienna,PChar(S)); można by zastopić StrPCopy(Zmienna,S+#00);
Jest tylko po to aby dodać znak 0 na końcu.

0

Poniżej dlaczego tak bardzo chcę ją tutaj upakować:


library Security;

uses
  Windows, Classes, IdHTTP, ActiveX, ComObj, Variants, SysUtils , MD5, Base64;

{$R *.res}
Var
  Computer : PChar;

//------------------------------------------------------------------------------
//                      Zwalnianie biblioteki z pamieci
//------------------------------------------------------------------------------

procedure FreeDLL(Reason : Integer);
begin
 { biblioteka jest usuwana z pamieci}
  If Reason <> DLL_PROCESS_DETACH then Exit;
    {Usuwanie zarezerwowanej pamięci}
    FreeMem(Computer);
end;

//------------------------------------------------------------------------------
//                       Procedury do wyeksportowania
//------------------------------------------------------------------------------


//Zwraca serial mathboard
Function GetComputer: PChar; stdcall;
Var
  Get : String;
Begin
  Get := HashString(GetMotherBoardSerial);
  GetMem(Computer,Length(Get)+1);
  StrPCopy(Computer,PChar(Get));
  Result := Computer;
End;

exports  // eksportuj procedurę
  GetComputer name 'GetComputer',

begin
  DLLProc := @FreeDLL;
end.
0

Mam także pytanie czy do funkcji których wynikiem jest np. Boolean, Integer także muszę rezerwować pamięć przez GetMem?

0
function GetComputer:String; stdcall;
begin
  Result:=HashString(GetMotherBoardSerial);
end;

Wywal:
Computer : PChar;
oraz:
FreeMem(Computer);

I nie potrzebujesz żadnych rezerwacji, Nie jasne zresztą po kiego pakujesz to w DLL?

0

_13th_Dragon Nie chce używać funkcji których rezultatem sa stringi, bo musiałbym do programu używać biblioteki bodajże borlandmm.dll do obsługi stringów.

0
Rafał D napisał(a):

Mam także pytanie czy do funkcji których wynikiem jest np. Boolean, Integer także muszę rezerwować pamięć przez GetMem?

Nie - do typów prostych nie potrzeba rezerwować pamięci, chyba że zapragniesz sobie je przekazywać poprzez wskaźniki.

0

Zapytam o jedno co ta twoja biblioteka zrobi jak wywołasz funkcję kilka razy i dopiero ją zwolnisz? Mi się wydaje że będzie wyciek pamięci.
Dlaczego nie zwracać wyniku jako jeden z parametrów?

function Foo(var Param: PAnsiChar; Size: Integer): Boolean; stdcall;

Wtedy alokujesz pamięć (GetMem) przed wywołaniem funkcji i zwalniasz (FreeMem) po. Wszystko robisz w aplikacji i jest to przejrzyste a nie udziwniasz...
W parametrach podajesz bufor i jego wielość. Funkcję w DLL musisz napisać tak aby sprawdzała czy tekst, który ma być zwrócony nie jest czasem większy niż wielkość bufora i odpowiednio reagowała.

0

A czemu nie za pomoca OleVariant?
np

function GetAsString(): OleVariant; safecall;
begin
  Result := 'Ala ma kota';
end;

export 
  GetAsStrin;

i teraz w exe


var
  DataProcedure = function(): OleVariant; safecall;
  Data: HModule;
begin
  Data := SafeLoadLibrary('MyDll.dll')
  @DataProcedure := GetProcAddress(Data, 'GetAsString');
  Showmessage(DataProcedure);
  FreeLibrary(Data);
end;

pisze z pamieci wiec cos moze nie dzialac.

1 użytkowników online, w tym zalogowanych: 0, gości: 1