![]() |
String/Char-Pointer aus C# DLL korrekt auslesen
Hallo,
erst mal ein frohes Neues Jahr. Ich habe leider noch eine „ungelöste“ Aufgabe aus dem alten Jahr: Die Ausgangssituation ist folgende: Ich habe in mein Delphi-Programm eine C#-DLL eingebunden, über die eine eigene Datenbank gemanagt wird. Zwischen meinem Programm und der DLL müssen also jede Menge Daten ausgetauscht werden. Dabei handelt es sich um numerische und alphanumerische Daten, die als Pointer übergeben werden müssen. Alle numerischen Daten werden problemlos wechselseitig ausgetauscht. Die Übergabe von Strings als „Pansichar“ funktioniert auch in eine Richtung: Übergabe von Delphi an die DLL. Nur umgekehrt hapert es. Ich kann keine Daten sauber auslesen und weiterverarbeiten. Dabei gibt es DLL-Routinen, die aufeinander aufbauen und korrekt funktionieren. Beispiel: Ich lese über eine Funktion eine Pansichar-Variable ein und übergebe den Inhalt (bzw. die Pointeradresse) wieder an eine andere DLL-Routine, die dann auch richtig ausgeführt wird. Das Problem liegt also „nur“ im Delphi-Programm. Hier 2 Basisfunktionen der DLL, die nacheinander aufgerufen werden: Function GetVarInfo(hFile:integer;iVar:Integer;out varname:pansichar;out varinfo:pinteger):Integer;stdcall; external 'c:\test\io32.dll' name 'GetVarInfo'; Function GetVarHandle(hFile:Integer;varname:pansichar;var varHandle:double):Integer;stdcall; external 'c:\test\io32.dll' name 'GetVarHandle'; “Getvarinfo” liefert den Variablennamen, den man an “Getvarhandle” wieder übergibt. Mit diesem Variablenamen werden in weiteren Funktionen die Daten der Datenbank abgerufen. Das funktioniert auch, aber ich kann mir den Variablenamen nicht richtig anzeigen lassen. Hier meine Aufruf-Routinen: var hFile,iVar:integer; varname2:pansichar; varhandle:double; varinfo:pinteger; zwst1:string[120]; begin fehler:=getvarinfo(hFile,iVar,varname2,varinfo); fehler:=getvarhandle(hFile,@varname2,varhandle); zwst1:=(ansistring(@varname2)); showmessage(zwst1); end; Ich bekomme leider die Variable „varname2“ nicht immer korrekt angezeigt. Normalerweise sollte ja der Inhalt einer Pointervariablen mit „^“ ausgelesen werden, aber damit bekomme ich nur eine Zugriffsverletzung. Mit der obigen Routine bekomme ich manchmal „varname2“ richtig angezeigt. „Manchmal“ heißt, je nachdem welche Datenbank ich öffne und einlese. Ich vermute, es ist ein Konvertierungsproblem, aber warum bekomme ich manchmal etwas angezeigt und manchmal nicht. Wie schon gesagt, wenn ich „varname2“ einer weiteren DLL-Funktion übergebe, um numerische Datensätze auszulesen, bekomme ich alle Datensätze richtig ausgelesen und angezeigt. Nur der Zugriff auf „varname2“ selbst funktioniert nicht korrekt. Hat jemand eine Idee? |
AW: String/Char-Pointer aus C# DLL korrekt auslesen
Du musst auch Speicher für varname reservieren, den die DLL dann befüllt.
|
AW: String/Char-Pointer aus C# DLL korrekt auslesen
Ich habe schon "new(varname2)" eingebaut. Nützt leider auch nichts.
Trotzdem danke für den Tipp. |
AW: String/Char-Pointer aus C# DLL korrekt auslesen
Bist Du sicher, dass das tatsächlich ein Ausgabeparameter ("out") ist? Normalerweise würde ich es ungefähr so versuchen:
Delphi-Quellcode:
var
varname2: AnsiString; begin SetLength(varname2, <Längenangabe>); fehler:=getvarinfo(hFile,iVar,PAnsiChar(varname2),varinfo); SetLength(varname2, StrLen(PAnsiChar(varname2))); |
AW: String/Char-Pointer aus C# DLL korrekt auslesen
Es ist auf jeden Fall eine Ausgabe, sonst könnte die 2. Funktion ja nicht damit weiterarbeiten.
Ich probiere jetzt eben deinen Vorschlag aus. Irgendwo in diesem Bereich vermute ich auch meinen Fehler. Danke schon mal... |
AW: String/Char-Pointer aus C# DLL korrekt auslesen
Ich bekomme leider beim Compilieren die Fehlermeldung für den Funktionsaufruf mit pansichar(...), dass ein Konstantenobjekt nich als Var-Parameter übergeben werden kann.
|
AW: String/Char-Pointer aus C# DLL korrekt auslesen
Deshalb ja meine Frage nach dem out. Was passiert, wenn Du das weglässt?
|
AW: String/Char-Pointer aus C# DLL korrekt auslesen
Ich habe zu der DLL die Info zur Strukur und die sieht so aus:
Delphi-Quellcode:
Ich brauche ja auch den Variablennamen. Manchmal (=je nach geöffneter Datenbank) bekomme kann ich ihn ja auch
int __stdcall GetVarInfo(
const int hFile, const int iVar, char* varName, int* varType); richtig angezeigt, aber manchmal nur teilweise oder auch garnicht. Warum bekomme ich eine Fehlermeldung im Programmablauf, wenn ich ansistring(@varname2) ändere in ansistring(varname2^). Das wäre doch eigentlich der korrekte Delphiuaufruf für einen Pointerinhalt. |
AW: String/Char-Pointer aus C# DLL korrekt auslesen
Wo steht da etwas von Ausgabeparameter? Ich sehe da char* varName, also einen Zeiger auf ein Zeichen, was PAnsiChar/PWideChar entspricht. Lass also das out weg und versuch es noch einmal wie gezeigt, das sollte nach meinem Dafürhalten funktionieren.
|
AW: String/Char-Pointer aus C# DLL korrekt auslesen
Habe ich mal ausprobiert, gibt leider einen "access violation" Fehler.
In der C#-Definition bedeutet "const", dass die Variable an die DLL übergeben werden muss und die mit "*" versehenen Variablen kommen zurück, also out. |
AW: String/Char-Pointer aus C# DLL korrekt auslesen
Ich bekomme offensichtlich die Pointeradresse zurück und kann sie auch weitergeben (siehe beide Funktionsaufrufe:
1. Aufruf einlesen von varname2, dann in der 2. Funktion Weitergabe der Pointeradresse an die DLL). Das funktioniert einwandfrei. Aber das Auslesen der Pointeradresse klappt leider nicht. |
AW: String/Char-Pointer aus C# DLL korrekt auslesen
Ich bin zwar kein Experte in C/C++/C#, aber rein syntaktisch sieht mir das eher nach C++ aus. In C# werden laut
![]() |
AW: String/Char-Pointer aus C# DLL korrekt auslesen
Es wird C++ sein, da kenne ich mich auch nicht richtig aus.
|
AW: String/Char-Pointer aus C# DLL korrekt auslesen
Ein Versuch noch:
Delphi-Quellcode:
Function GetVarInfo(hFile, iVar:Integer; varname: PAnsiChar; var varinfo: integer): Integer;stdcall;
external 'c:\test\io32.dll' name 'GetVarInfo'; ... var hFile, iVar: integer; varname2: AnsiString; varinfo: integer; begin SetLength(varname2, 1024); FillChar(varname2, Length(varname2), #0); fehler := GetVarInfo(hFile, iVar, PAnsiChar(varname2), varinfo); SetLength(varname2, StrLen(PAnsiChar(varname2))); ShowMessage(varname2); end; |
AW: String/Char-Pointer aus C# DLL korrekt auslesen
Ich hatte auch schon weiter experimentiert und das jetzt noch mal ohne "out" nachgebaut. Gab jetzt keine AV (war dann wohl vorhin doch noch ein anderer Fehler drin), aber habe trotzdem noch keinen Inhalt. Ich experimentiere jetzt mal ohne "out" weiter (sind ja 2 Funktionen mit "out").
Ich versuche es aber auch mit deinem erweiterten Ansatz. |
AW: String/Char-Pointer aus C# DLL korrekt auslesen
Ich habe jetzt "out" rausgenommen. und nach deiner Code auch die Variable null-terminiert, aber sie ist immer noch leer.
Allerdings gibt es auch keine AV mehr! |
AW: String/Char-Pointer aus C# DLL korrekt auslesen
Was steht denn in "fehler"?
|
AW: String/Char-Pointer aus C# DLL korrekt auslesen
Yep, hatte ich nicht mehr berücksichtigt, da vorher immer die "0" kam. Steht jetzt ein Wert drin.
Den prüfe ich jetzt mal. Danke erstmal. |
AW: String/Char-Pointer aus C# DLL korrekt auslesen
Das war's. Jetzt funzt es.
Herzlichen Dank für deine Unterstützung!!!:-D:-D |
AW: String/Char-Pointer aus C# DLL korrekt auslesen
Und woran lag es nun genau?
|
AW: String/Char-Pointer aus C# DLL korrekt auslesen
Primär lag es an dem "out" im Funktionsaufruf.
Ich war mir vorher sicher, dass ich nur Daten aus der Funktion bekomme, wenn das "out" vor der jeweiligen Variablen steht. Bei der stückweisen Anpassung des Programms kamen dann noch kleinere Fehler hinzu, wie bspw. ein falsche Dimensionierung der ansistring-Variablen (muss ja mind. Länge+1 sein wg. #0). Die 2. Funktion musste auch umgestellt werden, ansonsten wurde die Variable aus der 1. Funktion nicht gefunden (dadurch war dann fehler>0). Ich hatte lange an der Konvertierung ansistring/ansichar mit pchar, pwidechar, pansichar "rumgedoktert", da zwischen den Funktionen immer fehler=0 war und somit alles richtig übergeben wurde, aber eben nicht zuverlässig. Vielen Dank nochmal, so fängt das Jahr gut an!!!! |
AW: String/Char-Pointer aus C# DLL korrekt auslesen
OUT/VAR bedeutet, daß die "Variable" geändert werden kann, da eine Referenz auf den Speicher der Variable übergeben wird.
Das wird hier aber nur benötigt, wenn die Funktion den Speicher resserviert und dann den neuen Pointer zurückgeben muß. Hier wird aber nur ein "unveränderlicher" Zeiger übergeben und nur der Inhalt der aufgezeigten Speichers verändert. (Leider) kann man bei Pointern nicht angeben, ob der Inhalt des Speichers verändert wird (der Inhalt des referenzierten Speichers kann gelesen oder überschrieben werden), da IN/OUT/VAR/CONST nur eine Beziehung zur Variable selber haben. Der "Wert" der Variable, also die Adresse des Speichers, wird ja nicht verändert. Wenn man es genau nimmt, dann könnte eine
Delphi-Quellcode:
dennoch den Inhalt des strings verändern. (auch wenn standardmäßig die Compilermagic und die Prüfungen des Compilers versuchen das zu verhindern, was man aber böswillig umgehen könnte)
procedure IchBinBöse(const S: string);
|
AW: String/Char-Pointer aus C# DLL korrekt auslesen
Danke für deine Ausführungen himitsu. Das hilft mir auf jeden Fall weiter, da noch ein
paar weitere Routinen in der DLL enthalten sind, die ich auch brauche. Dann laufe ich nicht noch mal in dieselbe Falle:-D |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:50 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz