![]() |
PChar to String & zurück - Zeichen geht verloren
Hallihallo liebe Delphigemeinde
ein kleines (aber nerviges) Problem mit PChar und Strings.. Ich habe eine Funktion in eine .dll ausgelagert, das einbinden und aufrufen und so weiter funkzioniert auch. Allerdings, da die Funktionen ja ohne die Borlandbiliotheken keine Strings als Parameter übergeben können, habe ich PChar's verwendet. Nun Übergebe ich der Funktion einen PChar in dem "2+3" steht. Das kommt auch an. In der Funktio habe ich dann eine Variable vom Typ Sring erstellt und mittels
Delphi-Quellcode:
Den PChar wieder in einen String verwandelt.
String_var := Pchar_var;
Nun habe ich testweise einfach den String wieder in einen PChar konvertiert via
Delphi-Quellcode:
und zurückgeben lassen.. Allerdings kommt jetzt im Mutterprogramm nur noch der String "2+" zurück, d.h. das letzte Zeichen ist verlorengegangen..
result := PChar(String_var);
// Result ist natürlich vom Typ PChar.. Gesamt besteht meine Funkion aus:
Delphi-Quellcode:
Wahrscheinlich ist das ein wirklich dämlicher Fehler.. aber er macht mich verrückt.. plz help!
function aufreg(meinParameter: PChar): PChar;
var meinString: String; begin meinString := meinParameter; result := PChar(meinString); end; //Aufgerufen mit -> PChar('2+3') //Raus kommt -> 2+ MfG BliZZarD |
Re: PChar to String & zurück - Zeichen geht verloren
Füg dem String mal ein #0 hinzu und übergib den Pointer darauf, also @Str[1].
|
Re: PChar to String & zurück - Zeichen geht verloren
Das #0 am Ende des Strings ist immer da, soweit ich mich erinnern kann.
|
Re: PChar to String & zurück - Zeichen geht verloren
@Zacherl: Das hab ich jetzt nicht ganz kapiert.. Sry :-(
Würdest du mir ein kleines Codebeispiel spendieren? |
Re: PChar to String & zurück - Zeichen geht verloren
Wo wird den abgeschnitten? Kommt das richtige in der Dll an?
|
Re: PChar to String & zurück - Zeichen geht verloren
@mkinzler: ja in der dll kommts richtig an, wenn ich das hier mache:
Delphi-Quellcode:
Dann kommt ds richtige raus.. also muss es an den zwei Type-casts liegen..function aufreg(meinParameter: PChar): PChar; var meinString: String; begin result := meinParameter; end; |
Re: PChar to String & zurück - Zeichen geht verloren
Du gibts nen Pointer auf eine Lokale Variable zurück. Da ist es total zufällig was zurückgeliefert wird.
|
Re: PChar to String & zurück - Zeichen geht verloren
Dann versuch mal:
Delphi-Quellcode:
result := PChar(meinString+#0);
|
Re: PChar to String & zurück - Zeichen geht verloren
Und so?
Delphi-Quellcode:
function aufreg(meinParameter: PChar): PChar;
var meinString: String; begin meinString := StrPas(meinParameter); result := PChar(meinString); end; |
Re: PChar to String & zurück - Zeichen geht verloren
Nein versuchs so nicht. Funktionen geben keine PChars zurück. Nimm nen String oder packs als Parameter rein und lass die Aufrufende Funktion den Speicher allokieren.
|
Re: PChar to String & zurück - Zeichen geht verloren
Zitat:
|
Re: PChar to String & zurück - Zeichen geht verloren
@mkinzler: Danke.
/me sets mode: +gott mkinzler Das wars.. *freu* tausend dank xD Lösung falls jemand auch mal dieses Problem hat:
Delphi-Quellcode:
function aufreg(meinParameter: PChar): PChar;
var meinString: String; begin meinString := meinParameter result := PChar(meinString+#0); end; |
Re: PChar to String & zurück - Zeichen geht verloren
Wurde doch schon von Dax vorgeschlagen, habe nur seinen Vorschlag in deinen Code eingebaut.
|
Re: PChar to String & zurück - Zeichen geht verloren
Zitat:
Wenn man es anders löst, wird man sich vor nicht auffindbaren Speicherlecks nach einer Weile nicht mehr retten können. |
Re: PChar to String & zurück - Zeichen geht verloren
wtf? Entweder ich hab nen Denkfehler weil ich noch zu besoffen bin, hab das Prinzip von String/PChar in Delphi nicht verstanden oder ihr programmiert alle grauenhaft.
Strings werden von Delphi verwaltet, sind also auch gültig wenn man sie als Rückgabewert missbraucht. PChar ist das selbe wie ein Pointer. Und wenn ihr das so programmiert dann ist dieser Pointer nicht mehr gültig da dieser auf eine Lokale Variable zeigt. Sowas macht man eben nicht. Machs so wie MS mit ihren APIs: Sobald du PChars zurückbekommen willst, muss die aufrufende Funktion den Speicher allokieren und freigeben wenn sie den nicht mehr braucht. z.B. GetModuleFileName Meienr Meinung nach kann es auftreten, dass Delphi merkt, dass der lokale String nicht mehr benutzt wird und ihn überschreibt, bzw. dessen Speicher freigibt. Du arbeitest u.U. noch weiter mit diesem String (bzw. nur der Adresse) und es kann ggf crashen. Oder schreibt ihr auch so geniale Funktionen wie:
Delphi-Quellcode:
Wäre nett wenn mir mal jemand meine falsche denkweise erklärt.
function blub(a: integer): pinteger;
var s: integer; begin s := a; result := @s; end; Danke! Edit: Zitat:
Edit2: wer es testen will (Aufruf mit dem wort 'lol') Rückabe: lol
Delphi-Quellcode:
Rückgabe: lo
var
meinString: String; function aufreg(meinParameter: PChar): PChar; begin meinString := meinParameter; result := PChar(meinString); end;
Delphi-Quellcode:
function aufreg(meinParameter: PChar): PChar;
var meinString: String; begin meinString := meinParameter; result := PChar(meinString); end; |
Re: PChar to String & zurück - Zeichen geht verloren
Brechi hast vollkommen Recht. Es ist immer eine temporäre PChar Konvertierung und die verliert genauso ihre Gültigkeit wie auch die lokale string Variable mit verlassen der Funktion. Der Rückgabewert zeigt auf einen ehemals alloziierte/benutzten Block und von daher ist der Rückgabewert reiner Zufall. Grundlegend wird der Speicher bis zum auslesen des Wertes nicht erneut genutzt, und das ergibt hier den Anschein der Gültigkeit.
|
Re: PChar to String & zurück - Zeichen geht verloren
also GetMem benutzen.
|
Re: PChar to String & zurück - Zeichen geht verloren
Wie denn? In der DLL mit dem Speichermanager alloziieren und in der App mit deren Speichermanager wieder freigeben? Naja, ich sage dir jetzt schon, der eine weiss vom anderen nichts. Ausnahme: sharemem, aber dann kannste auch gleich Strings übergeben. Ich empfehle die schon zuvor genannte Methode wie es auch schon die WinAPI erfolgreich seit ein paar Jahren macht: App erzeugt einen Buffer und übergibt ihn. Siehe auch Luckies Tutorial dazu...
|
Re: PChar to String & zurück - Zeichen geht verloren
wenn die App den Buffer erzeugt, dann muss man auch erstmal wissen wie groß der Buffer sein soll.
GetTokenInformation macht das z.B. so. |
Re: PChar to String & zurück - Zeichen geht verloren
Zitat:
|
Re: PChar to String & zurück - Zeichen geht verloren
@ThE_-_BliZZarD:
Ich hoffe du beachtest die Einwände von Thomas und mir. Du hast vielleicht dein Problem kurzzeitig für deinen Beispielparameter gelöst. Die Lösung mit dem #0 ist einfach nur gefrickel und absolut unsicher. Wunder dich nicht wenn dein programm irgendwann mal einfach crashed. Benutze einen String als Rückgabewert. Das geht auch in dlls, dafür musst du dann aber als erste unit sharemem benutzen. Ansonsten kann das selbe Verhalten auftreten (manchmal gehts und manchmal nicht). Oder du benutzt den WinAPI Ansatz wenn du unbedingt einen PChar benutzen willst. Alles andere ist programmiertechnisch unsauber und nicht zu empfehlen. Auch wenn es nun den Anschein hat es funktioniert. Ich hoffe für alle die mal das selbe Problem haben, dass sie diesen Thread bis zum Ende lesen. |
Re: PChar to String & zurück - Zeichen geht verloren
Ich muss mich dem anschließen, es funktioniert nicht mehr. Also bis zurück in das Mutterprog hats mein Wert geschafft, aber dann ist Ende..^^
Ich hatte irgendwo schon ein Sourcebeispiel für eine Implementation ala GetModuleFileName() gesehn, leider finde ich sie nicht mehr :roll: Hoffe ihr könnt mir nochmal verzeihen und ein gaaanz kurzes Stück Beispielcode machen :-/ Denn, ich habe leider bisher noch nie selber Speicher angefordert/beschrieben geschweige denn wieder freigegeben.. Thx in advance, BliZZarD |
Re: PChar to String & zurück - Zeichen geht verloren
Delphi-Quellcode:
function PCharDLLFunktion(str: PChar): Integer;
var s: String; begin s := StringDLLFunktion; if str = nil then Result := Length(s) else begin try Move(s[1], str^, Length(s)); Result := -1; //Success except Result := -2; //Failure end; end; end; function NichtDLLFunktion: String; begin SetLength(Result, PCharDLLFunktion(nil)); if PCharDLLFunktion(@Result[1]) <> -1 then MessageBox('Fehler'); end; // Oder so ähnlich |
Re: PChar to String & zurück - Zeichen geht verloren
hmm.. warum wurde dort jetzt nichts mit Speicher allozieren/freigeben usw gemacht?
Oder reicht das für meine Zwecke schon. (man ist mir die Frage peinlich...) Allllllerdings, ich glaube das Problem behebt sich selbsttätig. Ich muss einer anderen Funktion in der DLL einen Record übergeben, der jede Menge kram enthält, und der soll in der DLL-Funktion geändert/erweitern werden und dann wieder zum Mutterprogramm zurückgegeben werden.. Dafür brauch ich ShareMem, oder? Und wenn ja.. dann kann ich ja auch gleich Strings verwenden, ne? Muss ich irgendwas beachten wenn ich ShareMem einsetze? Dazu 2 Fragen: 1. Wie kann ich sicherstellen, das die für ShareMem benötigten Bibliotheken (welche DLL's sind das?) auch beim Anwender vorhanden sind? Beim Start des Programms aus einer Resource extrahieren hilft ja nicht, da die DLL's ja schon beim Start geladen werden.. 2. Wie muss ich den Record übergeben, damit er im Unterprogramm geändert werden kann und diese Werte auch erhalten bleiben? Normal mit
Delphi-Quellcode:
?? Oder gibts da irgendwas special-artiges?^^
function DLLs_nerven_irgendwie(var MyKnoten: TKnotenFeld): Integer;
Danke leute, BliZZarD |
Re: PChar to String & zurück - Zeichen geht verloren
ShareMem muss als erste Unit in der dpr-Datei stehen, und wenn du die Anwendung weitergibst, musst du die Borlandmm.dll mitgeben.
|
Re: PChar to String & zurück - Zeichen geht verloren
1: Ja über SetLength wird Speicher reserviert, damit funktioniert obiges Beispiel
2: Das hängt ganz von deinem Record ab, denn es keiner Größenveränderung bedarf, dann funktioniert dein Beispiel bereits (mit Var übergibst du im Prinzip einen Pointer auf dein Record). |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:05 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 by Thomas Breitkreuz