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!
' schrieb:ich bin mal wieder auf Probleme gestoßen.
Ach Gott, wer hat die nicht.
Zitat:
Code:
SetLength(arr, n);
for i:=0 to n do
Wenn das Array N Elemente hat und bei 0 anfängt, wie groß ist dann der letzte Index: N oder N-1? (Das gilt im übrigen in Delphi wie in C++ wie in LV). Sei froh, dass du überhaupt was gesehen hast. Normalerweise führt eine Indexüberschreitung zu einer AccessViaolation.
Ich will doch mal kucken, wie ich das gemacht habe.
Jeder, der zur wahren Erkenntnis hindurchdringen will, muss den Berg Schwierigkeit alleine erklimmen (Helen Keller).
Von der Methode, den Speicher durch Delphi zur Verfügung zu stellen, rate ich ab. Möglicherweise sind die Memorymanager von Delphi und LV nicht kompatibel.
Besser ist, den Speicherbereich durch LabVIEW zur Verfügung zu stellen und durch Delphi die Daten dorthin schreiben zu lassen.
Wenn die Länge in LV unbekannt ist, wie folgt vorgehen: Länge aus DLL holen, Array in LV initialisieren, Pointer auf Datenwerte an DLL und Daten hinschreiben lassen.
Jeder, der zur wahren Erkenntnis hindurchdringen will, muss den Berg Schwierigkeit alleine erklimmen (Helen Keller).
Danke für die Infos! Das sieht richtig gut aus. Was ich noch nicht richtig verstanden habe, ist, was der Befehl
move(DynArr[0], PInt^, 4*anz);
macht. (Er übergibt die Daten:)OK). Die Delphi Hilfe hat mir da nicht weitergeholfen. Warum 4*anz, hat bestimmt was mit dem Pointer zu tun?
Kann man move auch verwenden wenn das Array 2-Dimensional ist?
MOVE = Speicher kopieren von Quelle nach Ziel. ANZ (respektive 4*ANZ) = Anzahl Bytes, die kopiert werden sollen. Da der Datentyp INTEGER ist, muss also die gewünschte Anzahl Integerwerte mit 4 multipliziert werden um auf die Anzahl der zu kopierenden Bytes zu kommen.
Zitat:Kann man move auch verwenden wenn das Array 2-Dimensional ist?
Im Prinzip ja. Voraussetzung wäre lediglich, dass die Daten linear hintereinander stehen.
Jeder, der zur wahren Erkenntnis hindurchdringen will, muss den Berg Schwierigkeit alleine erklimmen (Helen Keller).
' schrieb:Vielleicht kannst du das fix korrigieren?
Schau'mer mal.
Beachte Erstens:
In Delphi ist die Reihenfolge Länge/Breite andersherunm als in LV
Beachte Zweitens:
In Delphi kann jeder Index eine eigene Länge haben. z.B.:
SetLength(DynArr[0], 1234);
SetLength(DynArr[1], 12);
SetLength(DynArr[3], 234);
SetLength(DynArr[4], 34); usw.
Deswegen liegen die Daten des gesamten Felder nicht hintereinander.
Wegen beider Gründe kann also nicht mit einem move kopiert werden.
Jeder, der zur wahren Erkenntnis hindurchdringen will, muss den Berg Schwierigkeit alleine erklimmen (Helen Keller).
Folgendes passiert dann:
(1) Der erste Wert in der Schleife der DLL ist i:=0. D.h. müsste dann arr[i];=i+3 =0+3=3 sein. Im Ausgabearray in LV erscheint aber der Wert 4.
(2) Im Ausgabearray sind beim ersten Durchlauf schon drei Felder initialisiert mit diesen Werten (4,0,0). Warum?
(3) Erhöht man die "Arraylaenge" werden die drei initialisierten Felder gefüllt (4,5,6). Bei weiterer Erhöhung der Arraylänge, werden keine anderen Werte mehr ausgegeben.
Hallo,
Tschuldigung, wenn ich mich hier mal kurz einklinke, habe nämlich nicht so viel Ahnung von Delphi, hab zwar Programmierung mit Turbo Pascal begonnen, bin aber im Studium auf C umgepolt worden...
Vielleicht solltest Du folgendes beachten:
Bei LabVIEW sieht ein eindimensionales Array im Speicher so aus, daß die ersten 4 Byte die Anzahl der folgenden Feldelemente in Form einer vorzeichenbehafteten 32-Bit-Zahl (I32) angeben. Erst danach folgen dann die einzelnen Feldelemente. Ein LabVIEW-Feld hat daher immer mindestens eine Größe von 4 Byte, auch wenn es leer ist. In diesen Bytes stehen bei einem leeren Feld nur Nullen.
Wenn Du dann genau auf diesen vier Bytes herumschreibst, interpretiert LabVIEW das als geänderte Feldlänge und dann bekommst Du eine Fehlermeldung (oder LabVIEW wird mal eben beendet ), weil LabVIEW dann auf Speicherplätzen sucht, die gar nicht dafür reserviert sind, bei der Speicherfreigabe sieht's ähnlich aus.
Daher ist es sicherer, vor dem Aufruf von externem Code, sei's als CIN oder als DLL-Knoten, ein Feld mit der erwarteten Größe zu initialisieren (also muß Elementtyp und Feldgröße vorher bekannt sein), dieses dann an die externe Funktion zu übergeben und dort dann nur die ermittelten Werte auf die jeweilige bereits reservierte Speicherposition des übergebenen Feldes zu kopieren. Dann liegt die Speicherreservierung und -freigabe ausschließlich bei LabVIEW.
Ich glaube, mich daran zu erinnern, daß bei Pascal zumindest bei Strings das erste Byte die String-Länge gespeichert hat. Ein String ist ja auch nur ein Feld. Wenn nun Felder genau so aufgebaut sind, ist das obige Ergebnis nicht verwunderlich. Das erste Byte wird in der nicht angezeigt, weil es die Länge beinhaltet und die 3 angezeigten sind die 3 restlichen des LabVIEW-Feld-Kopfes.
Weiß aber nicht, ob man das von Pascal nun auf Delphi so übertragen kann, habe von der Entwicklung nichts mehr mitbekommen. Aber es ist nur so 'ne Idee.
' schrieb:Wenn Du dann genau auf diesen vier Bytes herumschreibst, interpretiert LabVIEW das als geänderte Feldlänge und dann bekommst Du eine Fehlermeldung (oder LabVIEW wird mal eben beendet ), weil LabVIEW dann auf Speicherplätzen sucht, die gar nicht dafür reserviert sind
Genau so kann es sein - das dumme nur ist: Es muss nicht so sein. Der aber trotzdem vorhandene Fehler macht sich dann erst drei Jahre später beim Kunden bemerkbar.
Zitat:Dann liegt die Speicherreservierung und -freigabe ausschließlich bei LabVIEW.
Genau dieses sollte immer angestrebt werden, ob man nun Felder, Strings, PChar oder gar Klassen aus einer (Delphi-)DLL lesen will.
Zitat:Ich glaube, mich daran zu erinnern, daß bei Pascal zumindest bei Strings das erste Byte die String-Länge gespeichert hat.
Auch für Strings ist die Zeit nicht stehengeblieben. Der von dir beschriebene String heißt in Delphi ShortString, ein normaler String ist ein ANSISTRING bzw. WideString. Ein "normaler" String kann bis zu 2GB Daten aufnehmen und hat anstelle von nur ein Byte einen "Overhead" von 12 Byte.
Jeder, der zur wahren Erkenntnis hindurchdringen will, muss den Berg Schwierigkeit alleine erklimmen (Helen Keller).