Wenn dein Problem oder deine Frage geklärt worden ist, markiere den Beitrag als "Lösung",
indem du auf den "Lösung" Button rechts unter dem entsprechenden Beitrag klickst. Vielen Dank!
ich habe eine Delphi DLL, die verschiedene Messgeräte abfragt und den Messwert als String zurückgibt. Da die Messgeräte seriell abgefragt werden, ist die Messrate leider zu langsam. Diese DLL wird über ein Delphi Programm angesprochen.
Da LabVIEW sehr flexibel ist um Messdaten zu erfassen, möchte ich nun die vorhandene DLL durch eine mit LabVIEW erstellte DLL ersetzen. Die Schnittstelle soll identisch bleiben, Änderungen am Delphi Programm sind nicht möglich.
Die Funktionsdeklaration der Delphi DLL sieht etwa so aus:
function getWert(pEinstellungen :pChar, pGeraet :pChar, bAbs :boolean):string
Nun habe ich versucht, in LabVIEW eine solche DLL zu erzeugen. Mit fürs Erste speichere ich mit der DLL die übergebenen Parameter in einer Textdatei. Wenn ich das Programm ausführe, werden nur unlesbare Zeichen in die Datei geschrieben.
ich weiß ist ein etwas exotisches Problem, hoffe ihr könnt mir helfen.
' schrieb:Die Funktionsdeklaration der Delphi DLL sieht etwa so aus:
"Etwa" ist für einen Programmablauf immer schlecht: Entweder sie sieht so aus oder nicht. Wenn sie anders (mal vom Komma, das ein Strichpunkt sein sollte, abgesehen) aussieht, könnte es vielleicht ja doch einfach gehen.
Ich befürchte, das geht so nicht - zumindest in einfacher Weise. pEinstellungeen, pGeraet und bAbs würde man vielleicht noch hinbekommen. Einen Rückgabewert String hab ich nicht hinbekommen. LV hat sich geweigert, den Rückgabewert von void auf String - oder was immer - zu setzen. Nun gut.
Eine Möglichkeit gibt es aber: Wrapper-DLL. Das ist eine solche DLL, die sowohl das LV-DLL-Format als auch das Delphi-DLL-Format kann. Die Delphi-Applikation ruft die Wrapper-DLL mit dem obiger Format auf. Die Wrapper-DLL holt sich aus der LV-DLL die Daten mittels des LV-DLL-Formats. Die Wrapper-DLL sollte in Delphi geschrieben sein - wegen des Rückgabewertes String.
Nebenbei bemerkt:
Einen Rückgabewert String würde ich nicht machen: wegen des Speichermanagers. LV und Delphi haben jeder seinen eigenen Speichermanager - und sie sind nicht kompatibel. Am sichersten ist immer ein PChar auf Speicher, den das aufrufende Programm zur Verfügung stellen muss.
Jeder, der zur wahren Erkenntnis hindurchdringen will, muss den Berg Schwierigkeit alleine erklimmen (Helen Keller).
das mit einer zwischen DLL habe ich mir auch schon überlegt, ist halt doppelte Arbeit, man muss dann 2 Schnittstellen verwalten. Grundsätzlich habe ich monentan aber (noch) nicht das Problem mit dem Rückgabewert, sondern mit den Übergabewerten, die sich ja mit einer Wrapper DLL vom Format her nicht ändern würden. Bei LV müsste man ja "Pascal String Zeiger" auswählen, was den pChar wohl am Besten entspricht.
Nun kann ich diese jedoch momentan nicht verarbeiten...
' schrieb:Bei LV müsste man ja "Pascal String Zeiger" auswählen, was den pChar wohl am Besten entspricht.
Wenn in deinem Funktionskopf PChar steht, dann ist das ein PChar und nicht ein "Pascal String Zeiger". PChars gibt es auch in Pascal/Delphi. PChar heißt dann in LV "C-String-Zeiger".
Jeder, der zur wahren Erkenntnis hindurchdringen will, muss den Berg Schwierigkeit alleine erklimmen (Helen Keller).
' schrieb:Wenn in deinem Funktionskopf PChar steht, dann ist das ein PChar und nicht ein "Pascal String Zeiger". PChars gibt es auch in Pascal/Delphi. PChar heißt dann in LV "C-String-Zeiger".
' schrieb:Wie sieht dann ein Pascal-String-Zeiger aus?
Der Zeiger selbst ist (bzw. zeigt auf) eine Adresse im Hauptspeicher, an der sich der C- bzw. Pascal-String befindet. Ein Zeiger in Win32 ist 32 Bit lang.
Ein Pascal-String ist eine Zeichenkette, an deren Anfang die Länge der Zeichenkette steht. Die Länge kann zwischen 0 und 255 (also ein Byte) liegen. Ein C-String ist eine Zeichenkette, an deren Ende ein #0 steht. C-String ist unter den Begriff PChar bekannter.
Wenn du in der Onlinehilfe in der LV-IDE nach StringHandle suchst, findest die die Erkärung zu C-String unf Pascal-String.
Im übrigen besteht ein Unterschied zwischen einem Pascal-String und einem String in Delphi. In Delphi benutzt praktisch niemand mehr Pascal-Strings (die dann ShortString heißen oder mit string[len] definiert werden). Auch in Delphi werden C-Strings, also PChar, benutzt. Nur in besonderen Fällen und unter Zwang wird ein Pascal-String verwendet. Delphi-Strings haben neben der 32Bit-Länge noch einen Referenzzähler und werden vom Delphi-Speichermanager verwaltet. Daher ist eine Übergabe von Delphi-Strings (wie bei dem Rückgabewert deiner Funktion, aber auch als Parameter in der Funktion) aus oder nach DLL's außerst kritisch - und sollte vermieden werden (eben wegen der Portierbarkeit zu Sprachen mit anderen Speichermanagern).
Die Parameter in deiner Funktion sind alles PChars.
Im übrigen wirst du Probleme bekommen mit der Übergabe des Wertes von bAbs. LV-DLLs scheinen eine Übergabe "by value", so wie es in deinem Funktionskopf steht, nicht zu können (bzw. wollen). LV-DLLs können anscheinend Daten nur "by reference" (also über Pointer) übergeben.
Wenn mir (oder wem auch sonst) nicht noch was einfällt, wirst du um eine Wrapper-DLL nicht herumkommen.
Jeder, der zur wahren Erkenntnis hindurchdringen will, muss den Berg Schwierigkeit alleine erklimmen (Helen Keller).
Ich habe nun das Problem mit einer speziellen Wrapper DLL gelöst.
... dabei die Windows Registry etwas zweckentfremdet. Das Ganze funktioniert wir folgt:
Das LabVIEW Programm schreibt vortlaufend Messwerte in die Registry. Eine neue Delphi DLL wird wie die alte angesprochen, jedoch spricht diese nicht die Messgeräte an, sondern liest lediglich die Werte aus der Registry. Nach den Lesen wird ein Flag auf 0 gesetzt. LV setzt dieses nach Aktualisierung wieder auf 1, dadurch kann festgestellt werden, ob die Werte aktuell sind.
Das Ganze ist somit für die Anwendung genügend und kann auch ohne Tools analysiert werden (F5 gut festhelten ).