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 

Einbinden einer DLL, Speichermanagement



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!

13.10.2009, 15:41
Beitrag #1

Mictlantecutli Offline
LVF-Grünschnabel
*


Beiträge: 13
Registriert seit: Aug 2009

2010
2009
kA

2.....
Deutschland
Einbinden einer DLL, Speichermanagement
Hallo allerseits,
ich arbeite seit kurzem mit LabVIEW und bin jetzt auf ein Problem gestoßen, das ich nicht gelöst bekomme. Ich würde mich daher sehr freuen, wenn mir jemand weiterhelfen könnte.
Also folgendes: Ich möchte die Funktionen einer DLL nutzen. (Mit Hilfe der DLL kommuniziere ich mit einem externen Gerät). Dazu benutze ich den Block "Aufruf externer Bibliotheken". Der Funktionsprototyp lautet:

Code:
unsigned int GetData(double **X, double **Y);
Das Einbinden der DLL funktioniert einwandfrei, LabVIEW erkennt die exportierten Funktionen der DLL problemlos. Bei den Parametern habe ich die folgenden Einstellungen gemacht:

Typ: Array
Datentyp: 8-Byte-Double
Dimension: 1
Array-Format: Array-Handle
An die Ein- und Ausgänge des LabVIEW-Blocks habe ich zum Testen Bedien- bzw. Anzeigeelemente gehängt.

Die DLL-Funktion allokiert selbstständig den von ihr benötigten Speicher, den man mit einer weiteren DLL-Funktion wieder freigeben muss. (Leider kann ich nicht mehr Informationen zur Verfügung stellen, ich kenne nur die Funktionsprototypen und eine kurze Beschreibung, den Quellcode habe ich nicht.)
Das Problem ist, dass LabVIEW nach dem Aufruf entweder den Dialog "Nicht genügend Speicher zum Abschließen dieser Operation" anzeigt, oder direkt nach der Ausführung abstürzt. (Unabhängig davon, ob ich die Funktion zum Freigeben des Speichers aufrufe oder nicht.) Ich denke mal, da kommen sich die DLL und der Speichermanager in die Quere, oder?
Tja jedenfalls weiß ich nicht genau wie ich die Funktion behandeln soll, sodass keine Speicherkonflikte entstehen.

Ich hoffe, ich konnte mein Problem hinreichend beschreiben... Ach ja, das VI habe ich nicht mit hochgeladen, da es ohne das Gerät nicht korrekt ausgeführt werden kann. Und noch etwas: Die DLL wurde schon in mehreren C-Projekten genutzt, wo sie einwandfrei funktioniert.
---
LabVIEW Version 8.6.1f1
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
Anzeige
13.10.2009, 18:09
Beitrag #2

IchSelbst Offline
LVF-Guru
*****


Beiträge: 3.689
Registriert seit: Feb 2005

11, 14, 15, 17, 18
-
DE

97437
Deutschland
Einbinden einer DLL, Speichermanagement
' schrieb:
Code:
unsigned int GetData(double **X, double **Y);
Aus deinem Posting entnehme ich, dass X und Y zwei Arrays sind. Stimmt das so?

Zitat:Array-Format: Array-Handle
Hm. Hm.
Double** ist zuerst mal ein Poiner auf einen Pointer, der auf ein Double zeigt - also nicht zwangsläufig ein Array-Handle. Ich glaube der Array-Handle beginnt mit der Arraygröße, nicht mit den Array-Daten (respektive einem Pointer auf die Arraydaten).

Zitat:Das Problem ist, dass LabVIEW nach dem Aufruf entweder den Dialog "Nicht genügend Speicher zum Abschließen dieser Operation" anzeigt,
Das entspricht aber einem Absturz.

Zitat:oder direkt nach der Ausführung abstürzt. (Unabhängig davon, ob ich die Funktion zum Freigeben des Speichers aufrufe oder nicht.)
Müsste mir klar sein, da ein double** kein Array-Handle ist, und somit DATA (also double** Data) im Norivana liegt.

Zitat:Ich denke mal, da kommen sich die DLL und der Speichermanager in die Quere, oder?
Nein, nicht unbedingt. Ich bin der Meinung, es liegt vielmehr eine ganz ordinärere AccessViolation vor. Da GetData Daten kopieren will (denk ich mal) vom DLL-Speicher in den LV-Speicher, sollte das mit den möglicherweise verschiedenen Speichermanagern funktionieren.

Zitat:Tja jedenfalls weiß ich nicht genau wie ich die Funktion behandeln soll, sodass keine Speicherkonflikte entstehen.
Probiers mal mit Zeiger auf Array-Handle.

Zitat:Und noch etwas: Die DLL wurde schon in mehreren C-Projekten genutzt, wo sie einwandfrei funktioniert.
Naja, da kann man ja die Aufrufparemeter solange anpassen, bis die double** entsprechen. Das geht eben in LV nicht. LV kennt keine Pointer auf Anwenderebene.

Wenn es unbedingt ein double** sein muss, würde das zwar mit Aufwand aber auch in LV gehen. Und zwar indirekt über einen MemMove. Ich glaube mich zu erinnern, dass es hier im Forum einen Thraed gibt, der darstellt, wie man einen Pointer in einem U32 abspeichert. Das zweimal ergibt dann einen Double**.

Ich hab gerade keine Zeit. Versuch mal selbst hier im Forum zu suchen.

Jeder, der zur wahren Erkenntnis hindurchdringen will, muss den Berg Schwierigkeit alleine erklimmen (Helen Keller).
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
13.10.2009, 18:59 (Dieser Beitrag wurde zuletzt bearbeitet: 13.10.2009 19:07 von rolfk.)
Beitrag #3

rolfk Offline
LVF-Guru
*****


Beiträge: 2.305
Registriert seit: Jun 2007

alle seit 6.0
1992
EN

2901GG
Niederlande
Einbinden einer DLL, Speichermanagement
' schrieb:
Code:
unsigned int GetData(double **X, double **Y);

Das ist wie Du schon richtig erkannt hast jeweils ein Pointer auf ein Array.

Zitat:Typ: Array
Datentyp: 8-Byte-Double
Dimension: 1
Array-Format: Array-Handle
An die Ein- und Ausgänge des LabVIEW-Blocks habe ich zum Testen Bedien- bzw. Anzeigeelemente gehängt.

Das geht leider so nicht. LabVIEW Arrays sind speziale LabVIEW Handles und müssen deshalb auch mit LabVIEW Funktionen alloziert und dealloziert werden. Da kannst Du nicht einen Speicherbereich der von einer DLL einfach so angelegt wird hineinwürgen. Auch die Pointer to Handle Option ist hier keine Lösung.

Zitat:Das Problem ist, dass LabVIEW nach dem Aufruf entweder den Dialog "Nicht genügend Speicher zum Abschließen dieser Operation" anzeigt, oder direkt nach der Ausführung abstürzt. (Unabhängig davon, ob ich die Funktion zum Freigeben des Speichers aufrufe oder nicht.) Ich denke mal, da kommen sich die DLL und der Speichermanager in die Quere, oder?

Das ist logisch und Deine Vermutung, dass das mit Speichermanagement zu tun hat trifft hier im Prinzip zu. Die DLL alloziert einen Speicher durch Aufruf von alloc() oder anverwandten Freunden und Du gibts Sie an LabVIEW zurück und sagst ihm schau das ist ein Arrayhandle. Irgenwann versucht LabVIEW das vermeintliche Arrayhandle anzusprechen oder auf seine eigene Weise zu deallozieren und läuft schrecklich ins Nirvana.

Zitat:Tja jedenfalls weiß ich nicht genau wie ich die Funktion behandeln soll, sodass keine Speicherkonflikte entstehen.

Da hängt davon ab was Du mit diesem Array in LabVIEW tun können musst. Grundsätzlich kannst Du diesen Arraypointer ganz einfach als Pointersized Integer behandeln (in Deinem Fall konfigurierst Du den Parameter als Pointersized Integer, Pass Pointer to Value). Dann bekommst Du in LabVIEW einen 32/64 Bit-Integer der den Pointer auf das Array representiert. Musst Du diesen Pointer "nur" an andere C Funktionen mittels Call Library Node übergeben, ist das Problem schon gelöst.
Willst Du dagegen die Daten im Array in LabVIEW auch noch lesen können, kommst Du nicht darum herum die entsprechende Information aus diesem Pointer herauszukopieren. Das kann man tun indem man die LabVIEW C Funktion MoveBlock() mittels Call Library Node aufruft.

Das geht ungefähr so:

Library Name: LabVIEW
Function Name: MoveBlock
Calling Convention: C
return value: void
1. Parameter: source, pointersized integer (Dein Pointer von Deiner Funktion)
2. Parameter: dest, Arraytype Deiner Wahl passed als C Array Pointer
3. Parameter: length, int32, passed as value, hier übergibst Du die Anzahl Byte die kopiert werden müssen, also Anzahl Arrayelemente * Arrayelement size in Bytes (8 für double Array)

Last but not least: Pointer die irgendwann angelegt wurden sollten auch wieder dealloziert werden. Deine DLL sollte dazu entsprechende Funktionen exportieren oder die Dokumentation sollte erwähnen, welche (OS-)Funktion dazu verwendet werden sollte. Verwendung von free() ist jedenfalls keine Option, da die DLL und der Aufrufer zwei verschiedene Versionen der C Runtime Library verwenden könnten und dann ist ein Speicherbereich, angelegt in der einen Runtime, undefiniert innerhalb der anderen.

Rolf Kalbermatter
CIT Engineering Netherlands

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
14.10.2009, 08:33
Beitrag #4

Mictlantecutli Offline
LVF-Grünschnabel
*


Beiträge: 13
Registriert seit: Aug 2009

2010
2009
kA

2.....
Deutschland
Einbinden einer DLL, Speichermanagement
Hallo IchSelbst, hallo rolfk,
ich danke Euch vielmals für die schnellen und ausführlichen Antworten! Mit der Anleitung von rolfk habe ich das Problem sehr schnell lösen könnenTop2. Alleine wäre ich da wahrscheinlich nie drauf gekommen...

Viele Grüße

Mictan
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
30
Antwort schreiben 


Möglicherweise verwandte Themen...
Themen Verfasser Antworten Views Letzter Beitrag
  Einbinden einer DLL mit mehr Output-Parametern, als Input-Parametern Herm 3 6.255 14.06.2011 11:12
Letzter Beitrag: rolfk
  DLL in LV einbinden. Geht es nur mit einer anderen Wrapper-DLL Dimitri 24 27.166 02.07.2010 15:16
Letzter Beitrag: Dimitri
  Einbinden einer dll (*.so) Apu 3 6.333 08.03.2010 19:51
Letzter Beitrag: rolfk
  Problem beim Einbinden einer DLL preacha 18 19.225 25.09.2008 11:51
Letzter Beitrag: baliik
  Einbinden einer Delphi-dll Svenni 6 8.377 17.10.2006 12:05
Letzter Beitrag: Svenni

Gehe zu: