LabVIEWForum.de
Problem beim Einbinden einer DLL - 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: Problem beim Einbinden einer DLL (/Thread-Problem-beim-Einbinden-einer-DLL)

Seiten: 1 2


Problem beim Einbinden einer DLL - preacha - 07.01.2008 16:16

Hallo,

bin neu hier im Forum und in der LabVIEW-Programmierung.
Folgende Problemstellung:
Ich habe eine DLL mit Funktionen zum Ansteuern einer Laserkamera von der Firma Keyence.
Zu dieser DLL gibt es auch schon ein Beispielprojekt für Visual Studio und dort funktioniert alles einwandfrei.
Meine Aufgabe ist es jetzt, mit Hilfe dieser DLL ein Programm für LabVIEW zu basteln.
Dazu habe ich versucht über "Werkzeuge -> Import -> Bibliothek" mit Hilfe des Assistenten die DLL einzubinden.
Ich folge also dem Assistenten, wähle die DLL aus (die Header Datei findet er auch gleich) und klicke auf weiter.
Ich includiere mal keine weiteren Pfade und klicke wieder auf weiter.
So, erstes Problem. Er findet 34 Funktionen, allerdings können nur 9 davon gewrappt werden. Bei den restlichen Funktionen kann er die Header-Datei "winsock.h" nicht finden.
Ok ich gehe zurück und includiere den Pfad in dem sich die besagte winsock.h befindet.
Nach erneutem klick auf weiter läd er eine weile und tut dann nichts. Ich komme nicht mehr weiter.
Gehe ich die ganze Sache falsch an? Wäre sehr dankbar für ein paar Denkanstöße.


Problem beim Einbinden einer DLL - jg - 07.01.2008 17:14

Moment, muss erst mal meine Kristallkugel konsultieren....

... OMMM ... OMMM ...
... OMMM ... OMMM ...

Sorry, sie zeigt nur undurchdringbaren Nebel an....

OK, Spass beiseite, lad mal nach Möglichkeit die Header-Dateien (und vielleicht noch die DLL und sonstige Dokumentationen) hoch, dann kann man vielleicht mehr sagen.

Der Import-Assistent von LV kommt auch nicht mit allem zurecht, vor allem Structures und Type-Definitions führen zu Problemen. Dann muss man das eben, falls überhaupt möglich, selber und von Hand machen.

MfG, Jens


Problem beim Einbinden einer DLL - preacha - 08.01.2008 08:20

Alles klar ich habe mal alles hochgeladen was ich habe.
Es handelt sich um die Datei "LJIF.dll" hoffe du kannst was damit anfangen.


Problem beim Einbinden einer DLL - rolfk - 08.01.2008 14:37

' schrieb:Alles klar ich habe mal alles hochgeladen was ich habe.
Es handelt sich um die Datei "LJIF.dll" hoffe du kannst was damit anfangen.

Also die Funktionen selber sind nicht sehr komplex und die struct Parameter scheinbar flat, also auch kein wirkliches Problem. Aber winsock.h ist ein ziemlich kompliziertes Header File und da verwundert es mich nicht so sehr, dass der Import_Wizard damit irgendwo Probleme bekommt.
An sich wäre winsock.h beinahe nicht nötig.

Rolf Kalbermatter

Ein Headerfile mit folgendem Inhalt anstelle von winsock.h sollte wahrscheinlich schon genügen:

#define BYTE unsigned char
#define WORD unsigned short
#define LONG signed long
#define DWORD unsigned long
#define BOOL long

#define LPCTSTR const char*

#define WINAPI stdcall

// All of above should be also possible to get from winbase.h

#define IN
#define OUT

struct in_addr {
union {
struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
struct { u_short s_w1,s_w2; } S_un_w;
u_long S_addr;
} S_un;
#define s_addr S_un.S_addr
/* can be used for most tcp & ip code */
#define s_host S_un.S_un_b.s_b2
/* host on imp */
#define s_net S_un.S_un_b.s_b1
/* network */
#define s_imp S_un.S_un_w.s_w2
/* imp */
#define s_impno S_un.S_un_b.s_b4
/* imp # */
#define s_lh S_un.S_un_b.s_b3
/* logical host */
};

typedef struct in_addr IN_ADDR;


Problem beim Einbinden einer DLL - preacha - 09.01.2008 09:22

Danke Rolf,

das hat wirklich geklappt, ich konnte die DLL mit dem Assistenten jetzt mit allen Funktionen importieren.
Leider hänge ich jetzt schon wieder.
Er hat jetzt für alle Funktionen ein vi erstellt. Soweit so gut.
Die erste Funktion die ich brauche ist "OpenDeviceEther" der ich als Parameter eine Struktur vom Typ "LJIF_OpenParam_Ethernet" mitgeben muss. Diese Struktur enthält jetzt die vier Teile einer IP-Adresse (über die sich die Kamera ensprechen lässt) als CInt.
Das ganze leitet sich wohl von der Microsoft-standard-struktur "IN_ADDR" ab, die auch in der Winsock.h definiert ist.

Aber wie erstelle ich in LabVIEW jetzt eine solche Struktur um sie der Funktion zu übergeben?

Leider habe ich nach dem Importieren eben auch einen Fehlerreport erhalten der genau von dieser Funktion spricht.
Ich hänge ihn mal an.

Edit:
Also ich habe jetzt mal ein wenig "rumprobiert" ^^
Laut einem Tutorial zum einbinden von DLL´s (habe ich hier im Forum irgendwo gefunden) kann man für Strukturen bzw Cluster einfach Arrays verwenden. Nach dem importieren der DLL erstellt er ja für den Parameter "openParam" einen leeren cluster. Den habe ich einfach mal gelöscht und übergebe für openparam jetzt ein umgewandeltes Array.
Er bringt dabei auch keine Fehlermeldung. Aber wenn ich jetzt auf Ausführen klicke gibt die Funktion mir als Hexadezimalzahl 2000 zurück. Was laut Helpfile heisst "Failed to open device".
Irgendwie bin ich auf dem Holzweg, oder?


Problem beim Einbinden einer DLL - rolfk - 09.01.2008 10:46

' schrieb:Danke Rolf,

das hat wirklich geklappt, ich konnte die DLL mit dem Assistenten jetzt mit allen Funktionen importieren.
Leider hänge ich jetzt schon wieder.
Er hat jetzt für alle Funktionen ein vi erstellt. Soweit so gut.
Die erste Funktion die ich brauche ist "OpenDeviceEther" der ich als Parameter eine Struktur vom Typ "LJIF_OpenParam_Ethernet" mitgeben muss. Diese Struktur enthält jetzt die vier Teile einer IP-Adresse (über die sich die Kamera ensprechen lässt) als CInt.
Das ganze leitet sich wohl von der Microsoft-standard-struktur "IN_ADDR" ab, die auch in der Winsock.h definiert ist.

Aber wie erstelle ich in LabVIEW jetzt eine solche Struktur um sie der Funktion zu übergeben?

Leider habe ich nach dem Importieren eben auch einen Fehlerreport erhalten der genau von dieser Funktion spricht.
Ich hänge ihn mal an.

Edit:
Also ich habe jetzt mal ein wenig "rumprobiert" ^^
Laut einem Tutorial zum einbinden von DLL´s (habe ich hier im Forum irgendwo gefunden) kann man für Strukturen bzw Cluster einfach Arrays verwenden. Nach dem importieren der DLL erstellt er ja für den Parameter "openParam" einen leeren cluster. Den habe ich einfach mal gelöscht und übergebe für openparam jetzt ein umgewandeltes Array.
Er bringt dabei auch keine Fehlermeldung. Aber wenn ich jetzt auf Ausführen klicke gibt die Funktion mir als Hexadezimalzahl 2000 zurück. Was laut Helpfile heisst "Failed to open device".
Irgendwie bin ich auf dem Holzweg, oder?

Array = Cluster ist meistens nicht korrekt. Jedenfalls nicht ohne sehr viel Kenntnis darüber wie die beiden Dinge durch einen C Compiler im Speicher angeordnet werden.

Also die von Dir angesprochene Funktion möchte gerne einen Pointer auf LJIF_OPENPARAM_ETHERNET. Das wiederum ist eine Struktur die die IN_ADDR Struktur enthält. Und IN_ADDR ist eine Union die entweder einen uInt32, zwei uInt16 oder vier uInt8 enthält. Für unsere Zwecke ist die uInt32 Variante am interessantesten. Eigentlich musst Du diesen Parameter nur als usigned 32-bit Integer konfigurieren der als Pointer to Value übergeben wird.

Dann kannst Du direkt den uInt32 den Du von der String to IP Funktion von der TCP Palette bekommst hiermit verbinden. Sollte so direkt gehen. Wenn nicht könnte die Byteorder verkehrt sein und dann müsstest Du noch eine Swap Bytes und Swap Words Funktion zwischen String To IP und diesem Eingang einfügen.

Rolf Kalbermatter


Problem beim Einbinden einer DLL - preacha - 09.01.2008 11:19

Rolf du bist ab sofort mein persönlicher Held. Ich hab zwar irgendwie keine Ahnung wieso, aber es hat tatsächlich funktioniert.
Super dickes Dankeschön.
Ich musste allerdings wirklich vorher eine Swap Bytes und Swap Words Funktion dazwischen schalten.
Jetzt wage ich mich mal an ein paar andere Funktionen.
Kann gut sein, dass ich deine unglaubliche Weisheit noch einmal brauche ;-)


Problem beim Einbinden einer DLL - preacha - 16.01.2008 08:44

Hallo, da bin ich wieder.
Ich konnte die letzten Tage leider nicht mehr weiter an der DLL arbeiten.
Jetzt bin ich aber wieder drann und hänge direkt wieder.
Jetzt geht es um die Funktion LJIF_GetMeasureValue.

Problem sind hier wieder die Parameter.
Wie ich nCount übergebe ist klar jetzt weiß ich aber nicht wie ich pMeasureData auslese.
Was muss ich mir hier jetzt in LabVIEW zusammenbasteln um die Werte anzeigen zu lassen?
Die Dll und Beispielcode für Visual Studio habe ich ja bereits oben angehängt.

EDIT:
So ich habe pMeasureData jetzt einfach mal als Array deklariert mit 4-Byte-Single Werten als Datenzeiger.
Er gibt mir jetzt auch Werte aus.
Allerdings noch nicht so ganz wie ich mir das vorstelle.
Und zwar sind z.b. im Moment die ersten 3 Ausgänge konfiguriert.
Im Beispielprogramm von Visualstudio gibt er mir also auch nur bei den ersten 3 Ausgängen die Werte aus.
Jetzt in LabVIEW wird das irgendwie verdreht und ich bekomme die Werte an Stelle 1,4 und 6 Ausgegeben.
Wenn ich also nCount(Was ja definiert welche Ausgänge ich abfragen möchte) auf 3 Stelle sehe ich nur den ersten Messwert.
An den anderen Stellen übergibt er mir 0 und an einer Stelle "NaN". Laut Hilfe müsste aber an den andern Stellen immer "Nan" zurückgegeben werden (was er in VS auch zurück gibt)
Weiß jemand woran das liegen könnte?
Ausserdem kann ich jetzt wirklich nur die Messwerte auslesen und nicht das enum mit den Fehlermeldungen.
Anbei jetzt mein aktuelles Projekt.


Problem beim Einbinden einer DLL - preacha - 21.01.2008 11:38

Hat keiner eine Idee woran das liegen könnte?
Er scheint irgendwie immer einen 0-Wert zwischen die elemente zu drücken.
Daher bekomme ich die Ausgänge 1-3 auch an stelle 2,4 und 6.
Wenn ich also maximal 8 Ausgänge habe werden es dann quasi doppelt soviel und nur jeder 2te Wert ist quasi ein echter Wert.

EDIT:

Kann es sein, dass dieser 0-Wert der sich da immer wieder einschleicht dieser Enum Wert ist? Dann passts ja eigentlich wieder ^^


Problem beim Einbinden einer DLL - IchSelbst - 21.01.2008 21:15

typedef enum {
LJIF_FLOATRESULT_VALID, // Valid data
LJIF_FLOATRESULT_RANGEOVER_P, // Overrange at the plus side
LJIF_FLOATRESULT_RANGEOVER_N, // Overrange at the minus side
LJIF_FLOATRESULT_WAITING, // Comparator standby
} LJIF_FLOATRESULT;

typedef struct {
LJIF_FLOATRESULT FloatResult; // Indicates whether data is valid
float fValue; // Measurement value when the value is "LJIF_FLOATRESULT_VALID". Indicates an invalid value in other situations.
} LJIF_MEASUREDATA;

EXP RC WINAPI LJIF_GetMeasureValue(OUT LJIF_MEASUREDATA* pData, IN int nCount);



Ich hab mal zusammengeschrieben, was notwendig ist. Schwierig, schwierig.

pData ist also ein Pointer auf eine Struktur! Ein einfaches Array of float geht hier also gar nicht. Jedes Arrayelement besteht auf einen Datum, das selbst aus zwei Daten besteht: einem Enumerator und einem Float. Leider weiß ich nicht, wie breit der Enzmerator ist. Kann sein ein Byte, zwei Byte oder auch vier Byte. Ein Array-Element kann also fünf Byte (das glaube ich aber nicht), sechs Byte (das halte ich für möglich) oder acht Byte haben (das wäre halt schön).

Du kannst mal folgendes probieren:

Mach einen Cluster aus "Result" und "Wert". Result definierst du als Byte (also I8) - oder Word (I16) oder Integer (I32). Wert als float. Den Cluster legt du in ein Array. Dieses Array gibst du auf den dll-Knoten. Den DLL-Knoten überlistest du wie folgt. Als Typ gibst du Array an, als Datentyp U8 (u - acht!), Dimensaion 1, Array-Format Array-Datenzeiger. Als Länge gibst du nichts an, sondern legst das Array wie oben an den DLL-Eingang. Und dann kuckst du was passiert.

Lv85_img