Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Parameterübergabe: was geht hier vor? (https://www.delphipraxis.net/45438-parameteruebergabe-geht-hier-vor.html)

weltaran 6. Mai 2005 12:15


Parameterübergabe: was geht hier vor?
 
Hallo Leute!

Zunächst ein bisschen Prosa vorweg: Ich schreibe eine DLL in Delphi. An das aufrufende Programm muss ich Zeichenketten zurückgeben. Das Aufrufende Programm kann so konfiguriert werden, dass es eine DLL mit folgender C-Syntax erwartet:

Code:
 (STDCALL)

 long int myfunction(wchar_t a[], wchar_t b[], wchar_t c[], wchar_t d[], wchar_t e[], wchar_t f[]);
Anmerkung: wchar_t ist ein WideChar in C.


Ich habe die entsprechende Funktion in Delphi so nachgebildet:
Delphi-Quellcode:
 function myfunction(a, b, c, d, e, f: Array of WideChar): longint; stdcall;
Jetzt das Problem: Ich kann zwar den String a (und c und e) verändern, aber bei den Strings b (und d und f) bekomm ich eine Zugriffsverletzung.

Ich habe dann den Spieß rumgedreht: Eine DLL in C geschrieben mit obigem Aufruf und die Anwendung in Delphi, die die DLL aufruft -> gleiches Ergebnis.

Wenn ich mir die Adressen der Arrays innerhalb der DLL anzeigen lasse, so bekomm ich für a[0], a[1], a[2], ..., c[0], c[1], c[2] ... plausible Werte (z.B. 1241104 dezimal, immer im korrekten Abstand von 2 Byte) angezeigt; für die anderen (b[0], b[1], ..., d[0], d[1], ...) werden jedoch sehr niedrige Adressen ausgegeben (z.B. 100, 102 dezimal).

Hat jemand von Euch eine Erklärung?

Ciao



P.S. die Problematik im Thread "Strings innerhalb DLL verändern" habe ich gelöst, deswegen ein neuer Thread

Mephistopheles 6. Mai 2005 12:18

Re: Parameterübergabe: was geht hier vor?
 
Übersetze die Arrays als PWideChar.

Speedmaster 6. Mai 2005 12:23

Re: Parameterübergabe: was geht hier vor?
 
Arrays kann man normal nicht ohne weiteres als Parameter übergeben!

Versuchs mal mit:
Delphi-Quellcode:
type
  TWideChar = Array of WideChar;
Dann den Typ in der Function benutzen, dannach sollte es funzen!

Muetze1 6. Mai 2005 12:46

Re: Parameterübergabe: was geht hier vor?
 
Moin!

Es sollte sogar ohne Probleme möglich sein direkt WideString als Typ anzugeben (ohne Array dann natürlich).

MfG
Muetze1

Mephistopheles 6. Mai 2005 12:58

Re: Parameterübergabe: was geht hier vor?
 
Zitat:

Zitat von Muetze1
Es sollte sogar ohne Probleme möglich sein direkt WideString als Typ anzugeben (ohne Array dann natürlich).

Häh? Bitte lesen -> http://www.manuel-poeter.de/hitcount...ls/Strings.zip

Das gilt auch für WideStrings.

Muetze1 6. Mai 2005 13:53

Re: Parameterübergabe: was geht hier vor?
 
Moin!

Zitat:

Zitat von Mephistopheles
Das gilt auch für WideStrings.

Nein, und da streite ich mich gerne mit dir.

MfG
Muetze1

Mephistopheles 6. Mai 2005 14:19

Re: Parameterübergabe: was geht hier vor?
 
Dann mal los.
Code:
CODE:004039D0 dd 8 ; <-- Länge des Strings
CODE:004039D4 aTest:                                 ; DATA XREF: CODE:00403A5Co
CODE:004039D4 unicode 0, <Test>,0
CODE:004039DE db   0
CODE:004039DF db   0
Einen Referenzzähler gibt es nicht, da hast du recht.
WideString ist ein sog. gezählter String und hat intern eine andere Struktur als PWideChar. Daher sind sie nicht einfach austauschbar, auch wenn der Compiler vielleicht aktuell für die korrekte Übergabe sorgt. Du verläßt dich hier auf undokumentierte Interna und könntest damit schnell verlassen sein. Deshalb generell Finger weg von Delphis Stringtypen wenn man andere Programmteile anspricht, die nicht die Delphistrukturen kennen.

Aber Argumente wäre soviel hilfreicher als "Nein, und da streite ich mich gerne mit dir." ;) ... ich lasse mich auch gern überzeugen.

Robert Marquardt 6. Mai 2005 14:28

Re: Parameterübergabe: was geht hier vor?
 
"array of" ist nie eine korrekte Konvertierung eines Zeigerparameters in C.
Als Parameter ist "wchar_t a[]" in C aequivalent mit "wchar_t *a".
Die korrekte Konvertierung nach Delphi lautet "a: PWideChar".

Man kann einen WideString via PWideChar(WideS) uebergeben, aber wenn die Funktion den String schreibt,
dann muss man vorher mit SetLength() eine genuegende Puffergroesse garantieren.

Mephistopheles 6. Mai 2005 14:33

Re: Parameterübergabe: was geht hier vor?
 
Zitat:

Zitat von Robert Marquardt
Als Parameter ist "wchar_t a[]" in C aequivalent mit "wchar_t *a".
Die korrekte Konvertierung nach Delphi lautet "a: PWideChar".

:thumb:

Zitat:

Zitat von Robert Marquardt
Man kann einen WideString via PWideChar(WideS) uebergeben, aber wenn die Funktion den String schreibt,
dann muss man vorher mit SetLength() eine genuegende Puffergroesse garantieren.

Es scheint auch mit WideString zu gehen. Habe mir das mal kurz im Disassembler angeschaut, wenn ich einen WideString an eine stdcall-Prozedur übergebe. In diesem Fall wird der Pointer auf die Zeichenkette übergeben. Aber darauf würde ich mich (s.o.) nicht verlassen.

weltaran 6. Mai 2005 16:15

Re: Parameterübergabe: was geht hier vor?
 
Hallo!


Ich habe nochmal einige Möglichkeiten durchgecheckt. Tatsache ist, dass ich Strings, die ich lediglich an die DLL übergebe und darin NICHT verändern will, mittels PWideChar übergebe und dies funktioniert tadellos. Mache ich das auch mit den zu verändernden Strings, so kommen nur Fragezeichen zurück:-(

Bei der aufrufenden Anwendung handelt es sich übrigens um TestStand von NationalInstruments. Die Hilfe sagt zur Übergabe von Strings folgendes:

Zitat:

In general, when you use string parameters, use one of the buffer types if
you want the DLL function to be able to change the contents of the
argument in TestStand. Use the C String or Unicode String type if the DLL
function does not modify the argument.

If you specify one of the string buffer types, the DLL-adapter copies the contents
of the string argument and a trailing zero element into a temporary buffer
before calling the DLL function. You specify the minimum size of the
temporary buffer in the Number of Elements control. If the string value is
longer than the buffer size you specify, the adapter resizes the temporary
buffer so that it is large enough to hold contents of the string argument and
the trailing zero element. After the DLL function returns, TestStand copies
the value that the function writes into the temporary buffer back to the
string argument.
If you specify the C String or Unicode String type, the adapter passes the
address of the actual string directly to the function without copying it to a
buffer. The code module must not change the contents of the string.

Ich habe die in C geschriebene Minimal-DLL auf TestStand losgelassen - keine Probleme. Aber ich will/muss nun mal Delphi für mein Projekt nehmen.



Ich forsche weiter an der Sache aber so langsam (nach etlichen Tagen! des Ausprobierens) habe ich die Schnauze voll.

So long.

weltaran


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:34 Uhr.
Seite 1 von 2  1 2      

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