INFO: Dieses Forum nutzt Cookies...
Cookies sind für den Betrieb des Forums unverzichtbar. Mit der Nutzung des Forums erklärst Du dich damit einverstanden, dass wir Cookies verwenden.

Es wird in jedem Fall ein Cookie gesetzt um diesen Hinweis nicht mehr zu erhalten. Desweiteren setzen wir Google Adsense und Google Analytics ein.


Antwort schreiben 

Pointer auf Subarray übergeben



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!

18.06.2012, 12:50 (Dieser Beitrag wurde zuletzt bearbeitet: 15.07.2012 17:28 von jg.)
Beitrag #1

Event Horizon Offline
LVF-Neueinsteiger


Beiträge: 8
Registriert seit: Jan 2009

7.1, 8.6
-
DE_EN

42653
Deutschland
Pointer auf Subarray übergeben
Hallo zusammen!

Ich habe hier ein USB-Oszilloskop, welches eine größere Anzahl Waveforms speichern kann.
Die beiliegenden DLLs enthalten eine Funkion, um den Buffer für jede einzelne Waveform festzulegen, sowie eine weitere Funktion, die die Daten anschließend aus dem Scope in die Buffer überträgt. In C sieht das etwa so aus:



Code:
int buffer1[1000];
int buffer2[1000];
int buffer3[1000];

Scope::SetBuffer(1, buffer1);
Scope::SetBuffer(2, buffer2);
Scope::SetBuffer(3, buffer3);


Scope::GetValues();


Nun sind es nicht nur 3 Buffer, sondern eher sowas wie 1000-10000, die Anzahl soll dynamisch sein.
In C macht man sich dann ein 2D-Array buffer[a][b], und übergibt der Funktion dann die einzelnen Subarrays buffer[a].

In Labview 8.6 bekomme ich das so statisch wie in dem COde-Beispiel hin, aber nicht dynamisch, da ich Probleme mit den Subarrays habe.


Ein Versuch war, für jede Wafeform ein einzelnes 1D-Array anzulegen, in die DLL-Funktion zu stopfen, und hinten zu nem 2D-Array zusammen zu tackern:

   
(Das ist grade auf die Schnelle hingemalt)

Problem: Beim Zusammentackern werden die Arrays intern an andere Speicherstellen verschoben, der nachfolgende AUfruf von GetValues führt dann lieber zum Crash von LV.

Ich könnte auch zuerst ein 2D-Array erzeugen, und dem SetBuffer Subarrays davon mitgeben. Funktioniert nicht, da bei den Subarrays offensichtlich immer Kopien der Daten erstellt werden.

Mäßigen Erfolg hatte ich mit Queues, in die ich die einzelnen Arrays stopfe. Crasht aber, wenn es zu viele Arrays werden.

Hat wer ne Idee, was ich da in LV 8.6 machen kann?

EDIT jg: Externer Bildlink gelöscht.
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
Anzeige
18.06.2012, 13:22 (Dieser Beitrag wurde zuletzt bearbeitet: 18.06.2012 13:34 von Kasi.)
Beitrag #2

Kasi Offline
LVF-Stammgast
***


Beiträge: 342
Registriert seit: Dec 2010

6 - 2009
2005
DE_EN

79194
Deutschland
RE: Pointer auf Subarray übergeben
Hab keine Lösung anzubieten, weil ich das Problem noch nicht ganz verstehe, daher frag ich einfach mal zurück:
Wie arbeitet denn "GetValues"? Solltest du der Funktion nicht direkt die Matrix übergeben, in die es die Werte schreiben soll? In deiner Skizze sieht dieser Aufruf ja sehr "unabhängig" aus.
Bzw. was liefert denn der Return-Wert der Funktion? Direkt eine Matrix?
Mmhmh... ich merke gerade, dass ich mich dem Thema noch viel weniger auskenne, als ich dachte...
...vielleicht kann Dir folgendes weiterhelfen: https://decibel.ni.com/content/docs/DOC-9091

If you're havin' serial communication problems I feel bad for you, son, I got 99 problems but a baud ain't one! (except if using USB2serial converters, then I experience serialous problems)
Webseite des Benutzers besuchen Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
18.06.2012, 15:03 (Dieser Beitrag wurde zuletzt bearbeitet: 15.07.2012 17:27 von jg.)
Beitrag #3

rolfk Offline
LVF-Guru
*****


Beiträge: 2.302
Registriert seit: Jun 2007

alle seit 6.0
1992
EN

2901GG
Niederlande
RE: Pointer auf Subarray übergeben
(18.06.2012 12:50 )Event Horizon schrieb:  Hallo zusammen!

Ich habe hier ein USB-Oszilloskop, welches eine größere Anzahl Waveforms speichern kann.
Die beiliegenden DLLs enthalten eine Funkion, um den Buffer für jede einzelne Waveform festzulegen, sowie eine weitere Funktion, die die Daten anschließend aus dem Scope in die Buffer überträgt. In C sieht das etwa so aus:



Code:
int buffer1[1000];
int buffer2[1000];
int buffer3[1000];

Scope::SetBuffer(1, buffer1);
Scope::SetBuffer(2, buffer2);
Scope::SetBuffer(3, buffer3);


Scope::GetValues();

Nun sind es nicht nur 3 Buffer, sondern eher sowas wie 1000-10000, die Anzahl soll dynamisch sein.
In C macht man sich dann ein 2D-Array buffer[a][b], und übergibt der Funktion dann die einzelnen Subarrays buffer[a].

In Labview 8.6 bekomme ich das so statisch wie in dem COde-Beispiel hin, aber nicht dynamisch, da ich Probleme mit den Subarrays habe.


Ein Versuch war, für jede Wafeform ein einzelnes 1D-Array anzulegen, in die DLL-Funktion zu stopfen, und hinten zu nem 2D-Array zusammen zu tackern:


(Das ist grade auf die Schnelle hingemalt)

Problem: Beim Zusammentackern werden die Arrays intern an andere Speicherstellen verschoben, der nachfolgende AUfruf von GetValues führt dann lieber zum Crash von LV.

Ich könnte auch zuerst ein 2D-Array erzeugen, und dem SetBuffer Subarrays davon mitgeben. Funktioniert nicht, da bei den Subarrays offensichtlich immer Kopien der Daten erstellt werden.

Mäßigen Erfolg hatte ich mit Queues, in die ich die einzelnen Arrays stopfe. Crasht aber, wenn es zu viele Arrays werden.

Hat wer ne Idee, was ich da in LV 8.6 machen kann?

Das geht so wie Du es tust absolut nicht.

1) Wenn die C Funktion einen Buffer von einer bestimmten Länge haben will musst DU den in LabVIEW auch allozieren und an die C Funktion übergeben, denn die C Funktion kann diesen Buffer nicht einfach vergrösseren wenn nötig, so wie LabVIEW das automatisch tut solange Du im Diagramm bleibst. Typisch macht man das mit der Initilize Array Funktion, aber......

2) LabVIEW Arrays sind nur während der Dauer des C Funktionsaufrufes garantiert um dort zu bleiben wo sie am Anfang des Aufrufs der C Funktion waren, danach ist LabVIEW frei um diese Arrays frei zu geben, wieder zu verwenden oder an einer anderen Stelle im Speicher zu verschieben. Diese Einschränkung lässt sich nicht wirklich entfernen, denn die ganze Optimalisierung von Speicherplatz und Ausführungszeit in LabVIEW beruht darauf dass LabVIEW den Speicher von Datenstrukturen jederzeit frei verschieben darf wenn es dies als notwendig erachtet.

Das einzige was Du tun kannst ist in der Loop selber jeweils einen Speicherbereich zu allozieren mit einem Aufrufe einer Speichermanagerfunktion und den daraus ergebenden Pointer an die Funktion zu geben. Und danach nach dem Du sicher weisst dass die DLL diese Buffer gefüllt hast, die Informationen aus diesem Pointer in eine genügend grosses LabVIEW Array kopieren. Und zu guter letzt auch nicht vergessen um jeden Pointer wieder ganz ordentlich zu deallozieren, ansonsten baust Du gewaltige Speicherlecks.

Dasselbe Problem hast Du übrigens in jeder Managed Umgebung wie etwa auch .Net wenn Du so ein Unmanaged API ansprechen willst.

Bedenke auch dass LabVIEW Datenflow ist und dass Daten im Wire zwar durch LabVIEW als Referenz benützt werden können zur Optimalisierung aber dass die Daten grundsätzlich immer By Value gesehen werden sollten. Der Pointer den Du mit SetBuffer an die DLL übergibst ist also möglicherweise einfach eine Kopie des ürsprünglichen Arrays, die nach dem Aufruf der Funktion freigegeben, da nicht mehr verwendet wird. Damit schribt GetValues in nun ungültigen Speicher und selbst wenn dieser Speicher nicht dealloziert wäre, würde GetValues in eine Kopie des ursprünglichen Arrays schreiben und nicht in das Array das Du dann im Indicator anzeigst.

Grundsätzlich ist also zu sagen dass dieses Oszi API nur von C aus zuverlässig aufgerufen werden kann und auch nur wenn Du einiges über Speicherverwaltung und Pointer weisst. Höhere Programmierumgebungen stolperen ganz einfach über das Problem, dass diese Managed Code voraussetzen und im Absenz verlangen, dass der Aufrufer des Unmanaged APIs die ganze Verwaltungsarbeit selber übernimmt.

Rolf Kalbermatter
Technische Universität Delft, Dienst Elektronik und Mechanik
https://blog.kalbermatter.nl
Webseite des Benutzers besuchen Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
18.06.2012, 16:04
Beitrag #4

Y-P Offline
☻ᴥᴥᴥ☻ᴥᴥᴥ☻
LVF-Team

Beiträge: 12.612
Registriert seit: Feb 2006

Developer Suite Core -> LabVIEW 2015 Prof.
2006
EN

71083
Deutschland
RE: Pointer auf Subarray übergeben
Offtopic2
Bitte Profil_ergaenzen. Da steht noch LabVIEW 7.1 drin.

Gruß Markus

(18.06.2012 12:50 )Event Horizon schrieb:  Hat wer ne Idee, was ich da in LV 8.6 machen kann?

--------------------------------------------------------------------------
Bitte stellt mir keine Fragen über PM, dafür ist das Forum da - andere haben vielleicht auch Interesse an der Antwort !!
--------------------------------------------------------------------------
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
07.07.2012, 18:08
Beitrag #5

Event Horizon Offline
LVF-Neueinsteiger


Beiträge: 8
Registriert seit: Jan 2009

7.1, 8.6
-
DE_EN

42653
Deutschland
RE: Pointer auf Subarray übergeben
Hallo zusammen!

Sorry für die Sendepause, ich hab noch 1000 andere Dinge nebenbei zu erledigen ;-)

Erstmal danke an rolfk für die ausführlichen Erläuterungen. Du hast recht, die Arrays müssen erstmal mit der benötigten Größe initialisiert werden. Das hatte ich auch im Original getan, das VI da ist nur ne Skizze, um das eigentliche Problem etwas besser hervor zu heben. Speicherverwaltung ist mir prinzipiell nicht fremd, nur wirds eben haarig, wenns um LV geht.


Zu der Sache mit dem selber Speicher alloziieren: Was genau schwebt dir da vor? LV 8.6 hat dafür anscheinend keine Funktionen. Im Prinzip stell ich mir grade vor, ein malloc() aus ner DLL zu nehmen, und dessen Rückgabewert - sofern größer 0 - dem setBuffer zu übergeben. Allerdings hab ich nun schon ein wenig mit einem malloc() rumgespielt, es scheint mir aber fast, daß der Speicher nach dem DLL-Knoten wieder freigegeben wird. So kann ich locker 1GB reservieren, das System zeigt danach aber nirgends einen so hohen Speicherverbrauch an.

Ansonsten bleibt wohl nur, ne eigene DLL als Wrapper um die ursprüngliche zu schreiben. Ich dachte, ich komm drumherum.
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
15.07.2012, 10:21 (Dieser Beitrag wurde zuletzt bearbeitet: 15.07.2012 10:25 von rolfk.)
Beitrag #6

rolfk Offline
LVF-Guru
*****


Beiträge: 2.302
Registriert seit: Jun 2007

alle seit 6.0
1992
EN

2901GG
Niederlande
RE: Pointer auf Subarray übergeben
(07.07.2012 18:08 )Event Horizon schrieb:  Hallo zusammen!

Sorry für die Sendepause, ich hab noch 1000 andere Dinge nebenbei zu erledigen ;-)

Erstmal danke an rolfk für die ausführlichen Erläuterungen. Du hast recht, die Arrays müssen erstmal mit der benötigten Größe initialisiert werden. Das hatte ich auch im Original getan, das VI da ist nur ne Skizze, um das eigentliche Problem etwas besser hervor zu heben. Speicherverwaltung ist mir prinzipiell nicht fremd, nur wirds eben haarig, wenns um LV geht.


Zu der Sache mit dem selber Speicher alloziieren: Was genau schwebt dir da vor? LV 8.6 hat dafür anscheinend keine Funktionen. Im Prinzip stell ich mir grade vor, ein malloc() aus ner DLL zu nehmen, und dessen Rückgabewert - sofern größer 0 - dem setBuffer zu übergeben. Allerdings hab ich nun schon ein wenig mit einem malloc() rumgespielt, es scheint mir aber fast, daß der Speicher nach dem DLL-Knoten wieder freigegeben wird. So kann ich locker 1GB reservieren, das System zeigt danach aber nirgends einen so hohen Speicherverbrauch an.

Ansonsten bleibt wohl nur, ne eigene DLL als Wrapper um die ursprüngliche zu schreiben. Ich dachte, ich komm drumherum.

Ist zwar "Tüplischiissen" aber der Aufruf von C Funktionen wird in LabVIEW nicht grundsätzlich schwieriger dann wenn Du die Funktion aus C selber aufrufst. Der Unterschied ist dass Du das in C dauernd, immer, zu jedem Zeitpunkt selber tun musst, in LabVIEW praktisch nur wenn Du die Call Library Node verwendest um externen Code aufzurufen. Das ist weil LabVIEW genau wie .Net eine Managed Umgebung ist, und C eben nicht.

Ich wundere mich von wo Du malloc() aufzurufen gedenkst. Das ist eine C Runtime Funktion die so nicht auf eine offiziell zugängliche Weise über eine Call Library Node aufgerufen werden kann. Natürlich gibt es sie in msvcrt.dll aber das ist laut Microsoft ein private API das eine Applikation nicht verwenden soll. Anstelle davon kannst Du entweder HeapAlloc() und HeapFree() in kernel32.dll verwenden. Oder die LabVIEW Memory Manager Funktionen DSNewPtr() und DSDisposePtr(). Die zweite Gruppe ist verfügbar wenn man in der Call Library Node als Librarynamen "LabVIEW" (ohne Anführungszeichen und Gross- und Kleinschreibung beachten) einführt. Die erste ist das Standard Windows Heap Management, auf dem grundsätzlich auch malloc() und die LabVIEW DSNewPtr() Funktionen letzten Endes aufbauen, aber sie sind etwas komplizierter im Aufruf.

Rolf Kalbermatter
Technische Universität Delft, Dienst Elektronik und Mechanik
https://blog.kalbermatter.nl
Webseite des Benutzers besuchen Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
Anzeige
Antwort schreiben 


Möglicherweise verwandte Themen...
Themen Verfasser Antworten Views Letzter Beitrag
  Datenübergabe an DLL Pointer to Pointer Reiling 2 8.362 02.02.2018 10:59
Letzter Beitrag: Reiling
  Absturz durch unzulässige Pointer VS_03 3 8.780 28.10.2016 18:32
Letzter Beitrag: VS_03
  dll mit Pointer auf komplexe Struktur einbinden Wedgewood 11 14.655 27.04.2014 23:44
Letzter Beitrag: Wedgewood
  Pointer auf Array mit Labview übertragen und darstellen lupus022 35 25.783 19.07.2013 10:53
Letzter Beitrag: lupus022
  Pointer und MoveBlock OXO 4 7.220 03.06.2013 16:31
Letzter Beitrag: OXO
  DLL-Einbindung, Struct mit verschiedenen Datentypen als Pointer übergeben hawk72 4 10.066 11.05.2012 14:41
Letzter Beitrag: hawk72

Gehe zu: