Delphi-PRAXiS
Seite 2 von 3     12 3      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   aus c-Programm eine Delphi-dll aufrufen (https://www.delphipraxis.net/84477-aus-c-programm-eine-delphi-dll-aufrufen.html)

DGL-luke 17. Jan 2007 15:58

Re: aus c-Programm eine Delphi-dll aufrufen
 
sollte es nicht so heißen:

Code:
*char c = func(...);
//oder
char[80] c = func(...); //da solltens dann aber auch 80 sein.
Alle C-Stringverarbeitungs-Funktionen sollten mit beidem eigentlich klarkommen.

Muetze1 17. Jan 2007 16:49

Re: aus c-Programm eine Delphi-dll aufrufen
 
Bei der Rückgabe eines PChars liegt das Problem mit dem Speichermanager vor. Die DLL alloziiert den Speicher für den String, du gibst die Adresse dessen zurück - aber beim verlassen der Funktion verliert der String seine Gültigkeit und der Speichermanager gibt den Platz wieder frei. Dies geschieht bei den Vorschlägen mit dem konstanten Array für die Rückgabe als Empfangsplatz genauso wie bei dem Vorschlag von sirius, welcher sogar offensichtlich einen temporären TypeCast durchführt.

Abhilfe würde hier nur die Übergabe eines entsprechend grossen Buffers helfen beim Aufruf, in welchen dann die Funktion diesen Rückgabestring reinlegt, wenn er denn genügend groß ist.

Mehr zu dem Thema hatte Luckie mal sehr schön zusammen gefaßt: [Artikel] Rückgabe von Strings aus DLLs

DGL-luke 17. Jan 2007 17:16

Re: aus c-Programm eine Delphi-dll aufrufen
 
Dass ein Result(!=lokale Variable) seine Gültigkeit verliert, wär mir neu - könnte aber durchaus sein, bei dem ganzen rumgewurschtle zwischen C und Delphi ;-)

Muetze1 17. Jan 2007 17:21

Re: aus c-Programm eine Delphi-dll aufrufen
 
Zitat:

Zitat von DGL-luke
Dass ein Result(!=lokale Variable) seine Gültigkeit verliert, wär mir neu - könnte aber durchaus sein, bei dem ganzen rumgewurschtle zwischen C und Delphi ;-)

Wenn das Result in 32 Bit reinpasst und kein Zeiger auf einen Speicherbereich darstellt, hast du recht. Aber PChar ist ein Zeiger und der Speicherbereich dazu wird vom Memorymanager angelegt. Da der Rückgabetyp ein PChar ist, wird bei der direkten Zuweisung eines konstanten Strings hier eine temporäre Typkonvertierung durchgeführt, also ist das folgende beides das gleiche:
Delphi-Quellcode:
// Result vom Typ PChar!
  Result := 'hallo ballo';
  Result := PChar('hallo ballo');
Und hier verliert der String seine Gültigkeit mit verlassen der Procedure, da die Variable aus einer Adresse besteht (da Pointer), welche ihre Gültigkeit behält und im Register übergeben wird. Nur halt an der Adresse steht nix mehr.

DGL-luke 17. Jan 2007 17:45

Re: aus c-Programm eine Delphi-dll aufrufen
 
danke.

Man muss es also explizit alloziieren? Reicht da Setlength?

Muetze1 17. Jan 2007 18:30

Re: aus c-Programm eine Delphi-dll aufrufen
 
Hängt davon ab, wo der String definiert ist, welchen du mit SetLength() setzt.

a) Wenn der String lokal innerhalb der Funktion deklariert ist, klappt dies nicht.
b) wenn der String global in der DLL deklariert ist würde es klappen. Dann kannst du auch einen temporären PChar() Typecast machen für das Result, weil durch die globale Variable in der DLL verliert der erzeugte Zeiger auf den String Inhalt nicht seine Gültigkeit mit verlassen der Procedure.

sirius 18. Jan 2007 07:53

Re: aus c-Programm eine Delphi-dll aufrufen
 
Zitat:

Zitat von Muetze1
// Result vom Typ PChar!
Result := 'hallo ballo';
Result := PChar('hallo ballo');[/delphi]
Und hier verliert der String seine Gültigkeit mit verlassen der Procedure, da die Variable aus einer Adresse besteht (da Pointer), welche ihre Gültigkeit behält und im Register übergeben wird. Nur halt an der Adresse steht nix mehr.

Ich bin mir nicht sicher, aber könntes es auch so sein, dass gerade bei solchen Festlegungen, die Zeichenkette ('hallo hallo') im Datensegment (oder im Codesegment; falls man überhaupt noch von Segmenten sprechen kann; auf jeden Fall nicht Stack) der DLL liegt. Und dies ist solange gültig, wie die DLL im Speicher liegt. Den Zeiger, den du mit PChar('hallo hallo') erstellst, zeigt also irgendwo direkt in den Code der DLL, wo die Zeichenkette liegt. Und bis freelibrary ist dieser gültig.

Anders wäre der Fall, wenn man eine Variable übergebn will (z.B. vom Stack), da müsste man in der DLL mit getmem/stralloc arbeiten und im C dann wieder "free"-n.


Edit: Oi, hier gabs ja schon eine Seite zwei. Den letzten Eintrag @Muetze hatt ich noch nicht gelesen. Aber genau der, trifft ja auf die Fragestellung zu.

Muetze1 18. Jan 2007 08:48

Re: aus c-Programm eine Delphi-dll aufrufen
 
Zitat:

Zitat von sirius
Anders wäre der Fall, wenn man eine Variable übergebn will (z.B. vom Stack), da müsste man in der DLL mit getmem/stralloc arbeiten und im C dann wieder "free"-n.

Aber da der Stack hier von zwei unterschiedlichen Speichermanagern verwaltet wird und es somit eigentlich sogar zwei Stacks gibt, ist dies nicht möglich. Das C Programm kennt keine Alloc-Info von dem Stack der DLL und umgekehrt. Daher kann das C Programm keinen Speicher auf dem Stack der DLL freigeben.

sirius 18. Jan 2007 09:10

Re: aus c-Programm eine Delphi-dll aufrufen
 
Zitat:

Zitat von Muetze1
Aber da der Stack hier von zwei unterschiedlichen Speichermanagern verwaltet wird und es somit eigentlich sogar zwei Stacks gibt, ist dies nicht möglich. Das C Programm kennt keine Alloc-Info von dem Stack der DLL und umgekehrt. Daher kann das C Programm keinen Speicher auf dem Stack der DLL freigeben.

Na klar sind das verschiedene Stacks. Deswegen ja auch getmem bzw. Stralloc (ich glaube getmem ist besser für C). Da landet nix auf dem Stack (außer der Pointer, aber den übergebe ich ja). Aber wir arbeiten ja nicht mit Variablen sondern mit einem zur Entwicklungszeit festgelegten Zeichenkette.

Muetze1 18. Jan 2007 09:37

Re: aus c-Programm eine Delphi-dll aufrufen
 
Zitat:

Zitat von sirius
Na klar sind das verschiedene Stacks. Deswegen ja auch getmem bzw. Stralloc (ich glaube getmem ist besser für C). Da landet nix auf dem Stack (außer der Pointer, aber den übergebe ich ja). Aber wir arbeiten ja nicht mit Variablen sondern mit einem zur Entwicklungszeit festgelegten Zeichenkette.

GetMem() wird vom Speichermanager implementiert. StrAlloc() greift auf GetMem() zurück. Der Speichermanager wiederrum verwaltet seinen eigenen Speicherbereich nach seinem eigenen gutdünken. Dabei alloziiert er nicht für diesen String Speicher von Windows (nicht direkt). Der Speichermanager hat seinen Pool von Speicher und er hat das Wissen darüber wo was wie gross alloziiert ist oder nicht. Wenn nun also Speichermanager 1 etwas in seinem Bereich alloziiert und verwaltet, dieser Speicherbereich zurück gegeben wird und bei Speichermanager 2 wieder freigegeben wird, dann kratzt sich der Speichermanager 2 nur am Kopf, schliesslich kennt seine Verwaltung keinen solchen Speicherbereich und auch die Adresse ist ihm suspekt. Daher kann er diesen Speicherbereich nicht freigeben.


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:42 Uhr.
Seite 2 von 3     12 3      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz