Biblioteka DLL a typ PAnsiChar

0

mam taki kod, i funkcje foo eksportuje z DLL na zewnątrz.

function GetSomeAnsiString():AnsiString;
begin
 Result:='bar';
end;

function foo():PAnsiChar;stdcall;
begin
 Result:=PAnsiChar(GetSomeAnsiString());
end;

wolno tak? Przecież PAnsiChar to tylko wskaźnik, co z tego wyniknie? Kod działa, ale jakie są konsekwencje? Na co to jest niby wskaźnik? Zmiennej nie ma przecież już, a mimo to tekst jest "pobieralny". Czegoś nie rozumiem.

0

borlndmm.dll - i GetSomeAnsiString można.
Natomiast foo() - masz sporą szansę że nawet bez DLL się wywali.

0

rzecz w tym że to działa i sie nie wywala, do tego program który pobiera tą zmienną nie jest w języku Delphi, nie jestem autorem kodu, ale napotkałem sie na to, i mnie to zastanawia. W jaki sposób jest przekazywany wskaźnik i jakim cudem zewnętrzny kod jest w stanie pobrać dane z tego bufora zanim on zostanie zwolniony... Nie mam wiedzy niskopoziomowej więc mnie to ciekawi.

czy to dlatego że w międzyczasie nikt inny nie nadpisał danego fragmentu pamięci nowymi danymi? Czy to jest magiczna furtka za sprawą której to "fuksem" działa?

1

Owszem, fuksem działa. Delphi ma garbage collektor dla napisów, więc jest non stop wyścig, kto pierwszy:
Garbage collector - to się wywali.
Program użyje i zapomni - wciąż działamy.

1

Jeśli chcesz zwracać wskaźnik na pamięć z funkcji to powinieneś pamiętać o tym, żeby nie zwracać wskaźników do zmiennych lokalnych. Jeśli już musisz zwrócić wskaźnik najpierw zaalokuj pamięć i zwróć do wskaźnik do tego obszaru pamięci. Jednak wtedy musisz po stronie funkcji wywołującej zwalniać tą pamięć. Trochę średnie rozwiązanie. O wiele lepiej by było aby funkcja wywołująca przydzielała pamięć, natomiast do funkcji przekazać wskaźnik, a funkcja niech wypełni pamięć danymi. Wtedy alokacja i zwalnianie pamięci jest w jednym miejscu i mamy mniejszą możliwość pomyłki.

1

@Adam samouk - zobacz tutaj: http://stackoverflow.com/questions/4269622/in-delphi-in-my-dll-do-i-have-to-allocate-the-return-pchar-of-a-function

W ten sam sposób działają niektóre (lub wiele - nie sposób sprawdzić) funkcje z WinAPI - zwracają łańcuch znaków przez parametr (a nie przez rezultat); Dla przykładu funkcja SHGetSpecialFolderPath - w parametrze pobiera bufor i uzupełnia go; Alokacja i dealokacja pamięci wykonywana jest po stronie programu, a funkcja z DLL tylko wypełnia danymi wskazany blok pamięci;

Przykład:

var
  arrPath: array [0 .. MAX_PATH] of Char;
begin
  if SHGetSpecialFolderPath(0, arrPath, CSIDL_LOCAL_APPDATA, False) then
    { macierz arrPath uzupełniona ścieżką katalogu } ;
end;

Możesz też poczytać komentarz wstawiany automatycznie przy tworzeniu nowego projektu biblioteki DLL - ten komentarz o module ShareMem; Ewentualnie przydatny wątek - http://stackoverflow.com/questions/8414972/delphis-sharemem-when-it-is-not-needed.

0

a co ze zmiennymi globalnymi zadeklarowanymi w DLL? Rzutowanie PAnsiChar zawsze będzie bezpieczne prawda?

0

Nie, tylko jeżeli kontrolujesz czas życia zmiennej.

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