Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Pchar Rückgabe (https://www.delphipraxis.net/1883-pchar-rueckgabe.html)

berbog 29. Dez 2002 11:02


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.

CalganX 29. Dez 2002 11:30

Hm... Wenn's nicht PChar, sondern String wäre könntest du das mit StrToInt machen (funktioniert auch mit Vorzeichen)...

Chris

Sebastian Nintemann 29. Dez 2002 12:18

Also bei mir funktionierts auch mit PChar:

Delphi-Quellcode:
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;
Keinerlei Meckereien von Delphi
Gruß, Sebastian

CalganX 29. Dez 2002 12:19

Ja gut.

Chris

berbog 29. Dez 2002 12:25

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.

DerKapitalist 29. Dez 2002 12:36

Code:
var
 p: PChar;
 i: integer;
begin
  p := PChar(edit1.Text);
  i := StrToInt(p);
end;
Klappt bei mir auch, warum sollet es auch nicht gehen, aber:

"4|" ist nunmal kein Zahlenwert -> deine Funktion liefert dir einen string und keinen Zahlenwert. Poste mal bitte den gesamten relevanten Code.

Sebastian Nintemann 29. Dez 2002 12:37

Hallo berbog, und wenn du mit string() typecastest?

Die Hilfe sagt aber das:

Zitat:

Zitat von Delphi Hilfe
You can mix long strings (AnsiString values) and null-terminated strings (PChar values) in expressions and assignments, and you can pass PChar values to functions or procedures that take long-string parameters. The assignment S := P, where S is a string variable and P is a PChar expression, copies a null-terminated string into a long string.
In a binary operation, if one operand is a long string and the other a PChar, the PChar operand is converted to a long string.

Gruß, Sebastian

DerKapitalist 29. Dez 2002 12:41

das mein ich ja auch, ich denke nciht,dass das was mit pChar zu tun hat

Sebastian Nintemann 29. Dez 2002 12:51

Ja, das vermute ich auch.
Zitat:

Zitat von berbog
Dieser Wert wird mir aber vorher bei der Zeile label4.caption := (analog1) richtig mit +0029 angezeigt

Wenn das so ist müss es doch funktionieren, stellst du zwischenzeitlich noch irgendwas mit dem PChar an? Du kannst ja mal ein bisschen Code posten bzw vorher nochmal prüfen, ob der String den du in Integer umwandeln willst auch wirklich eine gültige Zahl ist, sie wies aussieht siehts nämlich nicht so aus :spin:

Gruß, Sebastian

DerKapitalist 29. Dez 2002 12:55

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 :-)

berbog 29. Dez 2002 13:09

Hallo Alle

Hier der Code
Delphi-Quellcode:
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
[edit=Daniel B]Delphi-Tags; MfG Daniel B.[/edit]

DerKapitalist 29. Dez 2002 14:17

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]

Christian Seehase 29. Dez 2002 14:27

Moin Berbog,

zum einen schreibst Du

Zitat:

Dll Funktion analog1 wird ausgelesen und als Wert angezeigt
zum anderen deklarierst Du eine Varible mit dem Namen analog1.

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:

Zitat von DerKapitalist
Bei Übergabe von PChars erhaellst du naemlich keine Kopie der Daten sondern das Original.

Das dürfte wohl von der aufgerufenen Funktion abhängen.
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.

DerKapitalist 29. Dez 2002 14:35

@ 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

Christian Seehase 29. Dez 2002 14:55

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.

berbog 29. Dez 2002 17:17

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 ?

Luckie 29. Dez 2002 17:36

Kuck mal in der Hilfe unter DecimalSeparator.

Sebastian Nintemann 29. Dez 2002 18:08

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

berbog 29. Dez 2002 19:42

Hallo

Unter DecimalSeparator gibts keinen Eintrag (Schade)

label6.caption := 'Neuer Wert '+ (floattostr(strtofloat(analog1)));
bringt die gleiche Fehlermeldung

gruss Bernd

Brüggendiek 29. Dez 2002 20:06

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

berbog 29. Dez 2002 20:56

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

Brüggendiek 29. Dez 2002 21:50

Hallo Bernd!

Ist doch ganz einfach:

Code:
var
  DsSich : char;

begin
  DsSich := SysUtils.DecimalSeparator;
  SysUtils.DecimalSeparator := '.';

  // dein Code zur Umwandlung

  SysUtils.DecimalSeparator := DsSich;

end;
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!)

Gruß

Dietmar Brüggendiek

DerKapitalist 29. Dez 2002 22:52

@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?

berbog 29. Dez 2002 23:12

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

Christian Seehase 30. Dez 2002 02:25

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.

Brüggendiek 30. Dez 2002 15:50

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:
// Einstellungen vornehmen
try
  // Arbeiten
finally
  // aufräumen
end;
Dann wird auch bei einem Fehler noch aufgeräumt.
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