![]() |
Pchar Rückgabe
:freak: Hallo ich habe ein Anfängerproblem.
Als Rückgabe aus einer Dll bekomme ich einen Wert mit Vorzeichen zurück (z.b. +0029) wie wandele ich diesen in einen Integer Wert um. Danke im Voraus. |
Hm... Wenn's nicht PChar, sondern String wäre könntest du das mit StrToInt machen (funktioniert auch mit Vorzeichen)...
Chris |
Also bei mir funktionierts auch mit PChar:
Delphi-Quellcode:
Keinerlei Meckereien von Delphi
var
p: PChar; s: string; i: integer; begin s := '+2345'; p := PChar(s); i := StrToInt(p); Caption := IntToStr(i) //In der Caption stehts dann (bei +) ohne Vorzeichen end; Gruß, Sebastian |
Ja gut.
Chris |
Hallo Chris
Strtoint habe ich versucht, aber der compiler bringt mir eine Fehlermeldung (Im ProjektProjekt 1.exe ist eine Exception der Klasse EConvertError aufgetreten.Meldung "4|' ist kein gültiger Integer Wert'.) Dieser Wert wird mir aber vorher bei der Zeile label4.caption := (analog1) richtig mit +0029 angezeigt.Ich versuche diesen wert Im Diagramm (Chart) anzuzeigen. |
Code:
Klappt bei mir auch, warum sollet es auch nicht gehen, aber:
var
p: PChar; i: integer; begin p := PChar(edit1.Text); i := StrToInt(p); end; "4|" ist nunmal kein Zahlenwert -> deine Funktion liefert dir einen string und keinen Zahlenwert. Poste mal bitte den gesamten relevanten Code. |
Hallo berbog, und wenn du mit string() typecastest?
Die Hilfe sagt aber das: Zitat:
|
das mein ich ja auch, ich denke nciht,dass das was mit pChar zu tun hat
|
Ja, das vermute ich auch.
Zitat:
Gruß, Sebastian |
ja, oder bist du sicher, dass deine DLL nicht zwischenzeitlich den PChar modifiziert? Bei Übergabe von PChars erhaellst du naemlich keine Kopie der Daten sondern das Original.
Oder vielleicht hast du auch nicht Thread-safe programmiert. naja, möglich wärs ja :-) |
Hallo Alle
Hier der Code
Delphi-Quellcode:
[edit=Daniel B]Delphi-Tags; MfG Daniel B.[/edit]
var
analog1: Pchar; begin analog1 := strAlloc(20);//speicher reservieren label3.caption := inttostr ((ND_Readchanai(1,1,0,analog1)));// Dll Funktion analog1 wird ausgelesen und als Wert angezeigt label4.caption := (analog1); //wird richtig als +0029 ausgegeben Ist aber bis zur Fehlermeldung noch nicht passiert (wird Ohne follgende Zeile aber ausgegeben series1.AddX(strtoint(analog1));//erzeugt den Fehler |
hast du die DLL selbst geschrieben? Ist es möglich das non-printable ASCII Characters in der DLL rückgabe auftauchen? Weil warum sollte man einen Zahlenwert als PChar übergeben, wenn da nich was seltsames drinnen auftauchen kann, was keine zahl ist.
Ich kanns mir zwar nicht vorstellen, aber mach mal ein TypeCast von analog1 mit string (string(analog1)) bevor du StrToInt aufrufst, denn tatsaechlich wird der PChar auch typegecastet wenn du ihn Caption zuweist( TCaption = type string). Vielleicht gibts ja ein Problem mit dem #0 Zeichen eines PChars. keine ahnung, ausprobieren. naheliegender ist allerdings, dass analog1 nonprintable characters enthaellt nachtrag: mach mal strlen(analog1) -> Bekommst du wirklich 5 raus?[/code] |
Moin Berbog,
zum einen schreibst Du Zitat:
Hast Du jetzt also eine Variable und eine Funktion mit gleichem Namen? Dann wäre noch die Frage was die Dokumentation für die DLL Funktion über die zu übergebenden Parameter aussagt. Eine Meldung "4|" ist kein gültiger Integerwert weist eigentlich darauf hin, dass analog1 ins Nirwana zeigt und keinen definierten Wert enthält. Um zumindest vor Aufruf der Funktion zu wissen, was analog1 enthält solltest Du den Speicher ggf. mit AllocMem reservieren, oder aber mit FillChar/ZeroMemory auf binär 0 initialisieren (Achtung, bei AllocMem muss vermutlich ein Byte mehr reserviert werden als gedacht, um Platz für die terminierende 0 zu haben) @DerKapitalist Zitat:
Wenn der, wie zumindest in der Windows API meist üblich, ein Pointer auf einen Buffer übergeben werden soll, in den die Funktion ihr Ergebnis schreiben soll, wird es wohl eher eine Kopie sein. |
@ Christian
du hast ja recht mit dem Nirvana, das wuerde ich ja auch sagen, wenn er aber nicht vorher schonmal den richtigen Wert aus der Variable rausbekommen hat. Oder wie wuerdest du dir das sonst erklaeren? Ich kann mir das nur so erklaeren, dass die Variable von irgendwas modifziert wird |
Moin Kapitalist,
das seh' ich ähnlich. Eine Möglichkeit wäre, dass vor der Exception erzeugenden Zeile noch etwas passiert, was hier fehlt, eine andere, die so etwas mehr in Deine Überlegungsrichtung geht, wäre, dass die DLL die Adresse speichert, und immer wieder neue Werte reinschreibt. So etwas allerdings programmseitig abzufangen, wird interessant. ;-) Es fehlen halt noch Informationen über die Funktion. |
Hallo
Ich habe festgestellt, das der Rückgabewert noch eine Stelle hinter dem Komma enthält, die allerdings nicht durch Komma sondern einen Punkt getrennt ist. Das wurde allerdings nicht angezeigt. Nun gehe ich davon aus, das die Fehlermeldung durch den Dezimaltrennpunkt verursacht wurde. Weiß einer von euch wie ich eine entsprechende Umwandlung vornehmen kann ? |
Kuck mal in der Hilfe unter DecimalSeparator.
|
Hallo, außerdem musst du dann statt IntToStr bzw. StrtoInt FloatToStr bzw. StrToFloat nehmen da es sich dann ja nicht um eine Integer Zahl handelt.
Gruß, Sebastian |
Hallo
Unter DecimalSeparator gibts keinen Eintrag (Schade) label6.caption := 'Neuer Wert '+ (floattostr(strtofloat(analog1))); bringt die gleiche Fehlermeldung gruss Bernd |
Hallo Bernd!
Welche Delphi-Version hast Du denn? Bei mir reicht nach F1 im Index "deci" - und er zeigt mir "DecimalSeparator (Variable)" an. Die ist übrigens in der Unit "SysUtils", sollte man mit uses einbinden! Gruß Dietmar Brüggendiek |
Hallo Dietmar
Ich habe grade in einer Alten Version nachgesehen (delphi4), dort ist der Decimalseparator in der Hilfe vorhanden, in der aktuellen dagegen nicht aber trotzdem weiss ich nicht weiter. Gruss Bernd |
Hallo Bernd!
Ist doch ganz einfach:
Code:
Damit sichest Du den alten Wert in DsSich, setzt einen neuen Wert ('.') ein und speicherst nach Deinem Code den gesicherten Wert wieder zurück (Merke: immer hinterher aufräumen, sonst stolpern andere über Deinem Müll!)
var
DsSich : char; begin DsSich := SysUtils.DecimalSeparator; SysUtils.DecimalSeparator := '.'; // dein Code zur Umwandlung SysUtils.DecimalSeparator := DsSich; end; Gruß Dietmar Brüggendiek |
@Berbog: schau, genau das meinte ich. Wenn das aber nicht in der DLL Dokumentation drinnen stand, dann würde ich die DLL auch nciht weiter verwenden, vermutlich ist sie dann unsauber programmiert.
klappts jetzt eigtl. mit dem DecimalSeparator? |
Hallo
Ich Möchte euch allen danken Die Idee mit dem Decimalseparator war goldrichtig hier mein Code analog1:=strAlloc(20); decimalseparator:='.'; label11.Caption:= 'rückgabe TextToFloat '+ inttostr(typ); label3.caption := 'Fehler ' + inttostr ((ND_Readchanai(1,1,0,analog1)));// Dll Funktion analog1 wird ausgelesen und ergebnis angezeigt label4.caption := 'Messwert' +(analog1); //wird richtig als +0029 ausgegeben label5.Caption := 'Stringlänge ' + inttostr (strlen(analog1)); label6.caption := 'Neuer Wert ' +(floattostr(strtofloat(analog1))); series1.Addy((strtofloat(analog1))); Allerdings muss ich den Decimalseparator noch zurücksetzen Gruss Bernd :D |
Moin Dietmar,
grundsätzlich ist es eine sehr gute Idee aufzuräumen, nachdem man etwas verändert hat. DecimalSeparator gehört allerdings zu den Dingen, bei denen es nicht zwingend notwendig ist, falls nicht gerade mehrere Personen an dem Projekt arbeiten, oder arbeiten könnten. Dadurch werden ja keine Systemeinstellungen verändert, sondern nur eine SysUtils interne Variable geändert. |
Hallo Christian!
Natürlich werden bei DecimalSeparator keine Systemeinstellungen verändert, aber: Wenn man nicht daran denkt, zeigen andere Programmteile dann ein merkwürdiges Verhalten. Vielleicht benötigt der Programmierer an anderer Stelle ja den voreingestellten Wert - und eine Veränderung wirkt sich für den Rest des Programmlaufs aus! Nicht aufzuräumen führt dazu, daß andere Programmteile je nach Programmablauf unterschiedlich reagieren. Ausnahme: Die Einstellung wird im "initialization"-Abschnitt einer Unit durchgeführt und nicht von einer anderen überschrieben. Im Übrigen sollte man vielleicht noch ein Wenig Ressourcenschutz hinzufügen:
Code:
Dann wird auch bei einem Fehler noch aufgeräumt.
// Einstellungen vornehmen
try // Arbeiten finally // aufräumen end; Das ist besonders wichtig, wenn die Prozedur von irgendwo aufgerufen wird und dort mit TRY Fehler abgefangen werden (Merke: einmal TRY, immer TRY), da auch mehrfach verschachtelte Programmaufrufe bei Abbruch-Fehlern aller Art zum letzten geöffneten TRY zurückkehren und dort EXCEPT bzw. FINALLY ausführen. EXCEPT ist besonders eklig, weil dann ein Fehler bei IntToStr möglicherweise als "Dateifehler" angezeigt wird und die Ursache schwer zu finden ist. Gruß Dietmar Brüggendiek |
Alle Zeitangaben in WEZ +1. Es ist jetzt 01: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-2025 by Thomas Breitkreuz