DLL nie zwraca ciągu znaków tylko True

0
function START(Serwer:Word;nip:PAnsiChar;token:PAnsiChar):PAnsiChar; stdcall;
var pom : TFdllMain;
    tmp : PAnsiChar;
    tmp1: AnsiString;
    p1,p2,p3: string;
    x :Integer;
begin
  pom:= TfDLLMain.Create(Application);
    try
      pom.ShowModal;
      tmp1:= AnsiString(pom.wynik);
      tmp:= PAnsiChar(PAnsiString(tmp1));
      ShowMessage(tmp);
      REsult:= tmp;
    finally
      pom.Free();
    end;
end;

W Delphi pokazuje w wyniku ciąg znaków, ale kiedy uzywam w starym c++ to daje w wyniku True.

Pomocy.

5

Coś mi ten kod nie pasuje, ale nie widzę na razie oczywistego błędu. Lampka się zapala, bo to kod z DLL, a w nim używasz AnsiStringów, którymi niejawnie zarządza menedżer stringów, co może prowadzić do różnych dziwnych rzeczy. Gdybym sam musiał coś takiego zrobić, to bym po prostu zaalokował blok pamięci dla rezultatu, skopiował do niego ciąg znaków z pom.wynik, natomiast po stronie wywołującej bym ten ciąg znaków wykorzystał, a na koniec zwolnił.

Jeśli potrzebujesz działać na normalnych C-stringach, czyli np. typie PAnsiChar, który nie wskazuje na zawartość zmiennej typu AnsiString, to pamiętaj, że takie ciągi to zwykłe bloki pamięci, które spokojnie możesz alokować za pomocą GetMem/AllocMem, kopiować za pomocą Move, obrabiać w dowolny sposób, a na koniec zwalniać za pomocą FreeMem.

1

Jak widzę w DLL Create Application to mi miga i wyje, jak alarmy w burzową noc.
SwowMessage ... na jakimś poziomie legalne, ale zdecydowanie w złym duchu

Nawet w czystym Delphi to jedzie po bandzie, w tym z powodów wskazanych rpzez @furious programming

W Delphi pokazuje w wyniku ciąg znaków, ale kiedy uzywam w starym c++ to daje w wyniku True.

W żadnymi mi znanym dialekcie C++ nie ma True,
Trudno się zająć twoją uwagą bez określania o króryrm dialekcie / wersji mowa. generalnie raczej ma nie działać, niż od ręki działać jak się spodziewasz

0

funkcja zwraca PAnsiChar tylko czy ten string istnieje po zakończeniu funkcji ?

0

Ten problem jest mega prosty do rozwiązania, wystarczy użyć debuggera, biblioteka dll to zwykły program w C/C++ czy Delphi/Pascal, jeśli biblioteka w procesie zaalokowała jakąś pamięć i zwróciłą adres, a użytkownik sam ma zwolnić pamięć to bez problemu tak możesz sobie przekazywać obiekty, możesz też mega małe przez copy robić jeśli się mieszczą w rejestrze jak liczby.

W debugerze możesz zobaczyć co zwróciła funkcja, w jakim formacie itp.
Wiem, że assembler jest fajny, ale trzeba go używać, prawdziwy programista się nie boi debugować w assemblerze, jak dodasz symbole debuggera to będziesz mógł debugować w ojczystym kodzie źródłowym.
+
Eh googluj jakie są różnice między PAnisChar, a cstring itp.
Delphi ma czasem swoje smaczki jak pierwszy element stringa to liczba zawierająca jego długość, nie wiem czy dalej to jest, bo nie umiem tego języka, ale kiedyś tak to zaprojektowali.

1
Marius.Maximus napisał(a):

funkcja zwraca PAnsiChar tylko czy ten string istnieje po zakończeniu funkcji ?

Patrząc na ten kod, trudno jest powiedzieć, dlatego że menedżer stringów może robić magię. Ten pom.wynik znajduje się w obiekcie, który zostaje zwolniony na koniec, więc teoretycznie ten string zostaje dealokowany. Teoretycznie, bo linijka tmp1:= AnsiString(pom.wynik) może inkrementować licznik referencji i wtedy ciąg może istnieć na stercie po zniszczeniu obiektu pom. Dosyć niebezpieczna ta zabawa, w dodatku abstrakcje w formie menedżera stringów tylko ból głowy wywołują.

Rozsądnie będzie więc przyjąć, że refcount nie wchodzi w grę i po prostu finalizator zwalnia string z pamięci, przez co ta funkcja zwraca wskaźnik na śmieci. Rozwiązaniem może być po prostu ręczna alokacja bloku pamięci na stercie, skopiowanie zawartości ciągu i zwrócenie do niego wskaźnika.


NieZrobieTegoDobrze napisał(a):

W debugerze możesz zobaczyć co zwróciła funkcja, w jakim formacie itp.
Wiem, że assembler jest fajny, ale trzeba go używać, prawdziwy programista się nie boi debugować w assemblerze, jak dodasz symbole debuggera to będziesz mógł debugować w ojczystym kodzie źródłowym.

A na co komu assembly, skoro IDE ma narzędzia do podglądania zmiennych lokalnych? :|

Eh googluj jakie są różnice między PAnisChar, a cstring itp.

Żadne — C-String to zwykły wskaźnik na zwykłą tablicę bajtów, w której najbliższy początkowi znak NULL oznacza koniec zawartości ciągu (zawartości, ale niekoniecznie bloku pamięci). W Pascalach typ PAnsiChar to zwykły wskaźnik na znak, kompatybilny z C-Stringami.

Delphi ma czasem swoje smaczki jak pierwszy element stringa to liczba zawierająca jego długość […]

Typ AnsiString nigdy nie przechowywał swojej długości w pierwszym bajcie i trudno żeby przechowywał, skoro taki ciąg może mieć ~dowolną długość. Typ ten posiada metadane przed komórką zawierającą pierwszy znak, ale nie w formie jednobajtowego licznika, a czterobajtowego, tak samo jak licznik referencji.

[…] nie wiem czy dalej to jest, bo nie umiem tego języka, ale kiedyś tak to zaprojektowali.

No to skoro nie wiesz, to się nie wypowiadaj i nie wprowadzaj zamieszania, a swoją wiedzę z zakresu Turbo Pascala odnieś do najbliższego muzeum.

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