Function Test: PChar w bibliotece DLL

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;

Kopiuj
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?

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

Znalazłem jedno rozwiązanie w Google:

Kopiuj
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

Kopiuj
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
_13th_Dragon
  • Rejestracja:prawie 20 lat
  • Ostatnio:9 dni
0

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


Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
0

Miało być:

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

end;
_13th_Dragon
Dokładnie to samo robisz.
_13th_Dragon
  • Rejestracja:prawie 20 lat
  • Ostatnio:9 dni
0
Kopiuj
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;

Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
0
Kopiuj
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.

_13th_Dragon
Skąd ty wytrzasnąłeś tą Zmienna i po kiego chcesz ją tu na siłę wsadzić z uporczywością maniaka?
0

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

Kopiuj

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?

_13th_Dragon
  • Rejestracja:prawie 20 lat
  • Ostatnio:9 dni
0
Kopiuj
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?


Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
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.

edytowany 1x, ostatnio: olesio
_13th_Dragon
Zgadza się, z tym że ja nie pojmuję po kiego w ogóle chcesz to pakować do DLL.
Patryk27
Moderator
  • Rejestracja:ponad 17 lat
  • Ostatnio:prawie 2 lata
  • Lokalizacja:Wrocław
  • Postów:13042
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.


KA
  • Rejestracja:prawie 20 lat
  • Ostatnio:minuta
  • Lokalizacja:Gorlice
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?

Kopiuj
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.


Nie odpowiadam na PW w sprawie pomocy programistycznej.
Pytania zadawaj na forum, bo:
od tego ono jest ;) | celowo nie zawracasz gitary | przeczyta to więcej osób a więc większe szanse że ktoś pomoże.
crowa
  • Rejestracja:ponad 18 lat
  • Ostatnio:około 8 lat
  • Lokalizacja:Poznań
  • Postów:295
0

A czemu nie za pomoca OleVariant?
np

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

export 
  GetAsStrin;

i teraz w exe

Kopiuj

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.


Tomasz Andrzejewski
Delphi (XE3-XE7) framework engineer @ InterLan
MCP: Microsoft SQL Server 2008, Implementation and Maintenance

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.