LabVIEWForum.de
C-Funktion benötigt Struct - Druckversion

+- LabVIEWForum.de (https://www.labviewforum.de)
+-- Forum: LabVIEW (/Forum-LabVIEW)
+--- Forum: LabVIEW Allgemein (/Forum-LabVIEW-Allgemein)
+---- Forum: DLL & externer Code (/Forum-DLL-externer-Code)
+---- Thema: C-Funktion benötigt Struct (/Thread-C-Funktion-benoetigt-Struct)



C-Funktion benötigt Struct - Forest - 01.05.2013 14:03

Hallo und einen schönen Feiertag an alle...
Ich bin neu hier und beschäftige mich seit kurzem mit Labview - Die Forumssuche hat mich leider nicht so richtig weitergebracht, deshalb wollte ich hier doch nochmal direkt anfragen...
Mir wurde die Aufgabe gestellt Messwerte von Labview weiterzuverarbeiten. Hierfür soll auf eine libsvm zugegriffen werden.
Dabei muss allerdings einer C-Funktion ein Struct mit Integer und Double Datentypen mit den Messwerten übergeben werden.
Nun habe ich das Problem, dass meine Daten in einem Array oder wahlweise auch Cluster vorliegen können, ich diese aber nicht an die C-Funktion weitergegeben bekomme.
Ich hab schon versucht mir mittels einer DLL und den "Externe Funktionenaufruf-Knoten" mein Problem zu lösen, allerdings bekomme ich damit ja nur Integer oder Strings zurückgegeben.
Mir geht es also darum nen Array oder Cluster in Labview in ein Struct umzuwandeln - dieses Struct wird dann von einer C-Funktion weiterverarbeitet und soll als Struct zurückgeschieben werden und als Cluster oder Array von Labview gelesen werden können.

Hoffe ich konnte mein Problem schildern und würd mich sehr über Hilfe oder etwaige Nachfragen freuen... (Trotz Feiertag Blush)
Grüße
Forest


RE: C-Funktion benötigt Struct - Kasi - 02.05.2013 07:18

Es gibt dazu einen netten Thread auf lavag.org, außerdem noch ein ominöses Word-Dokument, welches aber etwa das Gleiche sagt. Hilft das?


RE: C-Funktion benötigt Struct - Forest - 02.05.2013 13:28

Hallo Kasi,
Danke für die Antwort.
Ich hab mich heute nochmal drangesetzt und erstmal versucht die Elemente eines einfachen Array durch nen c-File zu verändern und diese dann mit LabView wieder einzulesen.
Leider komm ich mit der Datenübergabe noch nicht so richtig weiter.

Hier mein C-Code:
.cpp:
#include "stdafx.h"
#include "Wert.h"
#include <iostream>

using namespace std;

// Dies ist das Beispiel einer exportierten Funktion.
WERT_API int* summieren(int n)
{
int *s = new int[3];
s[0] = n;
s[1] = n+1;
s[2] = 2;

return s;
}

.h:
#ifdef WERT_EXPORTS
#define WERT_API __declspec(dllexport)
#else
#define WERT_API __declspec(dllimport)
#endif

struct liste{
int a;
int b;
int c;
};

// Diese Klasse wird aus Wert.dll exportiert.
class WERT_API CWert {
public:
CWert(void);
// TODO: Hier die Methoden hinzufügen.
};

extern WERT_API int nWert;

WERT_API int* summieren(int n);

Hab mittels VisualStudio als Win32 Anwendung ne DLL erzeugt die ich über den "Knoten zum Aufruf externe Bibliotheken" aufrufe:
1. Problem: Als Aufrufkonvention habe ich stdcall(WINAPI) eingestellt - beim Ausführen spuckt mir Labview nen "ERROR 1097" aus mit dem ich aber nichts anfangen kann - Als Rückgabewert habe ich Nummerisch mit "Vorzeichenbehafteter Zeigergroßer Integer" gewählt.
2. bekomme ich es leider nicht hin mit Hilfe des zurückgegebenen Pointers auf das neue Array zuzugreifen:

Hier mal mein Modell:
[attachment=44528]
Die Parametrierung von dem MoveBlock habe ich von hier: https://decibel.ni.com/content/docs/DOC-9091

Hoffe hier kann mir einer weiterhelfen - komme mit den Datentypen anscheinend irgendwie nicht so richtig klar...
Vielen Dank für eure Hilfe


RE: C-Funktion benötigt Struct - rolfk - 04.05.2013 23:38

(02.05.2013 13:28 )Forest schrieb:  Hallo Kasi,
Danke für die Antwort.
Ich hab mich heute nochmal drangesetzt und erstmal versucht die Elemente eines einfachen Array durch nen c-File zu verändern und diese dann mit LabView wieder einzulesen.
Leider komm ich mit der Datenübergabe noch nicht so richtig weiter.

Hier mein C-Code:
.cpp:
#include "stdafx.h"
#include "Wert.h"
#include <iostream>

using namespace std;

// Dies ist das Beispiel einer exportierten Funktion.
WERT_API int* summieren(int n)
{
int *s = new int[3];
s[0] = n;
s[1] = n+1;
s[2] = 2;

return s;
}

.h:
#ifdef WERT_EXPORTS
#define WERT_API __declspec(dllexport)
#else
#define WERT_API __declspec(dllimport)
#endif

struct liste{
int a;
int b;
int c;
};

// Diese Klasse wird aus Wert.dll exportiert.
class WERT_API CWert {
public:
CWert(void);
// TODO: Hier die Methoden hinzufügen.
};

extern WERT_API int nWert;

WERT_API int* summieren(int n);

Hab mittels VisualStudio als Win32 Anwendung ne DLL erzeugt die ich über den "Knoten zum Aufruf externe Bibliotheken" aufrufe:
1. Problem: Als Aufrufkonvention habe ich stdcall(WINAPI) eingestellt - beim Ausführen spuckt mir Labview nen "ERROR 1097" aus mit dem ich aber nichts anfangen kann - Als Rückgabewert habe ich Nummerisch mit "Vorzeichenbehafteter Zeigergroßer Integer" gewählt.
2. bekomme ich es leider nicht hin mit Hilfe des zurückgegebenen Pointers auf das neue Array zuzugreifen:

Hier mal mein Modell:

Die Parametrierung von dem MoveBlock habe ich von hier: https://decibel.ni.com/content/docs/DOC-9091

Hoffe hier kann mir einer weiterhelfen - komme mit den Datentypen anscheinend irgendwie nicht so richtig klar...
Vielen Dank für eure Hilfe

Nun es gibt hier verschiedene Dinge anzumerken.

1) die Verwendung von alles Double-Controls die dann nach Belieben in die entsprechenden Datentypen gecoerced werden ist nicht nur unschön, sondern verschwendet auch Speicher und Performance, und nicht zuletzt macht es es mir unmöglich aus dem Bild zu ersehen ob Du nicht doch Datentypenfehler mit der Konfiguration der Call Library Nodes hast. Anhängen eines VIs, am besten abgespeichert nach ein paar Versionen früher ist absolut vorzuziehen.

2) ist aus Deinem kopierten Sourcecode nicht deutlich, was WERT_API ist. Das kann __stdcall sein aber auch etwas anderes.

3) produzierst Du ein Memoryleak von genau 12 byte (plus memory manager overhead) mit jedem Aufruf dieser Funktion. Da wird ein Array von 3 Integers mit new() alloziert aber das wird nirgends wieder frei gegeben. Da der von new() verwendete Memorymanager von der Compiler Version und der verwendeten Runtime library abhängt, kannst Du nicht irgendein willkürliches delete() verwenden, sondern musst Du das delete() in derselben DLL ausführen. Du kommst also nicht darum herum, eine weitere Funktion zu exportieren, die einen Pointer übernimmt und dann delete() aufruft, und natürlich musst Du diese Funktion auch schön brav aufrufen nachdem Du mit MoveBlock() die Daten herauskopiert hast.

Viel einfacher ginge es aber wenn Du einen Arrayparameter and die Funktion übergibst, diese Array in LabVIEW mit zum Beispiel ArrayInitialize anlegst und dann die Daten in der DLL direkt da hinein kopiers. Sparst Du Dir das ganze MoveBlock() getue, was auch wieder Performance und Speicher kostet, auch wenn das hier mit 3 * 4 Byte natürlich noch nicht spektakulär ist. Aber solche Basteleien verführen dazu um sie in der Zukunft wiederzuverwenden nur dann vielleicht für ein 200 MB grosse Bitmap, und dann klagst Du dass LabVIEW langsam ist weil es nicht 50 Frames pro Sekunde einlesen kann.