16.12.2009, 10:40
Beitrag #1
|
ghostwhisperer
LVF-Grünschnabel
Beiträge: 12
Registriert seit: Mar 2007
2009
1998
de
70469
Deutschland
|
Einbinden externen Code mit unbekannter Parameterstruktur
Hallo ! Ich weiss einfach nicht weiter und finde bislang auch hier kein passendes Thema...
Ich möchte Funktionen einer API einbinden, die für die Ansteuerung von Lichtschnittkameras geschrieben wurde.
Nun funktionierte von Anfang an nichtmal die Initialisierung der Kamera, da diese die Instanz eines sehr kompliziert aufgebauten Handlers erfordert.
Hab mir vom Händler eine API-Zusatzfunktion schreiben lassen, die die Instanzierung selbst vornimmt und mir "nur" den Zeiger auf die Datenstruktur
zurückgeben sollte. Das alles, damit ich in LabVIEW nicht alles neu programmieren muss, da der Aufwand ernorm wäre (Instanz einer Struktur mit unendlich vielen weiteren Unter-Strukturen).
Mich interessiert weder der Aufbau des Handlers noch der Inhalt. Ich muss nur den Zeiger auf den Handler an die Funktionen zur Kamerasteuerung weitergeben könnnen.
Und genau das schaff ich nicht. der Funktionsaufruf sieht so aus:
int LIBCALL SR_API_SetupCam ( Camdesc* cd1, Param* pars1)
Hab die Konfiguration des Knotens schon zigmal durchprobiert. Unter den vielen Möglichkeiten find ich einfach nicht die richtige....
Müsste doch eigentlich als Zeiger ein uint32 mit Übergabe "Zeiger auf wert" reichen oder nicht? Zeiger heisst doch einfach (Start-)Adresse im Speicher der Struktur-Instanz???? Bekomme aber immer das zurück, was ich auch reingebe, nämlich nen Nullpointer.
Wenn ich void* nehme funktioniert auch nix. Cstring-pointer, Arrayzeiger usw generieren LV-Abstürze.
Was ist eigentlich der Unterschied zwischen "Zeiger durch Wert" und "Zeiger in Handles" ??? Mich verwirrt das alles nur.
HILFÄÄ
Wer weiss Rat ??
MFG Torsten
|
|
|
16.12.2009, 10:54
Beitrag #2
|
Y-P
☻ᴥᴥᴥ☻ᴥᴥᴥ☻
Beiträge: 12.612
Registriert seit: Feb 2006
Developer Suite Core -> LabVIEW 2015 Prof.
2006
EN
71083
Deutschland
|
Einbinden externen Code mit unbekannter Parameterstruktur
Scheint eine Frage für "rolfk" oder "IchSelbst" zu sein.
Was anderes: Ist LabVIEW 6.1 echt noch Deine aktuelle Version? Wenn nicht, dann bitte
Gruß Markus
--------------------------------------------------------------------------
Bitte stellt mir keine Fragen über PM, dafür ist das Forum da - andere haben vielleicht auch Interesse an der Antwort !!
--------------------------------------------------------------------------
|
|
|
16.12.2009, 11:26
Beitrag #3
|
ghostwhisperer
LVF-Grünschnabel
Beiträge: 12
Registriert seit: Mar 2007
2009
1998
de
70469
Deutschland
|
Einbinden externen Code mit unbekannter Parameterstruktur
Hallo !
Ich ARBEITE mit LV2009. War nur ewig nicht im Forum.
Keine Ahnung wie ich vorgehen muss?
Hab eben was über Zeiger und Referenzen in C++ gelesen. Jetzt bin ich doppelt verwirrt. Was habe ich denn hier nun??
' schrieb:Scheint eine Frage für "rolfk" oder "IchSelbst" zu sein.
Was anderes: Ist LabVIEW 6.1 echt noch Deine aktuelle Version? Wenn nicht, dann bitte
Gruß Markus
|
|
|
16.12.2009, 14:22
Beitrag #5
|
ghostwhisperer
LVF-Grünschnabel
Beiträge: 12
Registriert seit: Mar 2007
2009
1998
de
70469
Deutschland
|
Einbinden externen Code mit unbekannter Parameterstruktur
Hallo und Danke erstmal.
Eigentlich stellt die Funktion der DLL schon einen speicherbereich zur Verfügung. Alle weiteren Funktionen brauchen als parameter nur "*camdesc". Dieser Parameter wird ja tatsächlich im Header der DLL beschrieben und nur von der DLL verwendet.
Reicht die Startadresse da wirklich nicht aus?
Ich habs mal mit dem u8 array probiert. Bekomme immer noch Nullwerte, wenn ich mir das Ausgangsarray betrachte. Oder liegt das nur an der falschen länge?
Andere Frage : wirklich u8? Ich dachte heut wird alles mit 32 bit adressiert.
MFG Torsten
' schrieb:Das ist zwar ein Pointer aber nicht einer der von der DLL zurückgegben wird sondern der vom Aufrufer bereitgestellt wird. Auch wenn Du den Inhalt dieses Pointers in LabVIEW nicht anschauen willst musst Du der Funktion halt schon einen Speicherbereich zur Verfügung stellen in den sie schreiben darf. Am einfachsten geht das mit Initialize Array indem du ein U8 Array erzeugst. Dann noch die richtige Länge in Bytes herausfinden und den entsprechenden Parameter in der Call Library Node als C Array Pointer konfigurieren und alles sollte soweit in Ordnung sein.
|
|
|
16.12.2009, 14:37
(Dieser Beitrag wurde zuletzt bearbeitet: 16.12.2009 14:38 von rolfk.)
Beitrag #6
|
rolfk
LVF-Guru
Beiträge: 2.305
Registriert seit: Jun 2007
alle seit 6.0
1992
EN
2901GG
Niederlande
|
Einbinden externen Code mit unbekannter Parameterstruktur
' schrieb:Hallo und Danke erstmal.
Eigentlich stellt die Funktion der DLL schon einen speicherbereich zur Verfügung. Alle weiteren Funktionen brauchen als parameter nur "*camdesc". Dieser Parameter wird ja tatsächlich im Header der DLL beschrieben und nur von der DLL verwendet.
Reicht die Startadresse da wirklich nicht aus?
Ich habs mal mit dem u8 array probiert. Bekomme immer noch Nullwerte, wenn ich mir das Ausgangsarray betrachte. Oder liegt das nur an der falschen länge?
Andere Frage : wirklich u8? Ich dachte heut wird alles mit 32 bit adressiert.
MFG Torsten
Also da ich nicht die ganze Headerdatei sehen kann muss ich hier natürlich Vermutungen machen aber die Deklaration
int LIBCALL SR_API_SetupCam ( Camdesc* cd1, Param* pars1)
lässt halt die Vermutung aufkommen dass es zwar ein Pointer ist aber eben nicht einer der von der DLL kommt. Das darum weil Camdesc und Param ziemlich sicher struct Deklarationen sind und nicht Pointer darauf. Also so was wie:
typedef struct {
sometype elm1;
sometype elm2;
.....
} Camdesc;
und nicht:
typedef struct {
sometype elm1;
sometype elm2;
.....
} *Camdesc;
Das heisst cd1 und pars1 sind zwar Pointer auf eine Struktur aber eben nicht Pointer die aus der DLL herauskommen. In C kann man nur Werte in einem Parameter zurückgeben indem man diesen Parameter als Referenz verwendet. Wenn die DLL also den Pointer zurückgeben wollte müsste der Pointer als Referenz übergeben werden was so aussehen würde:
int LIBCALL SR_API_SetupCam ( Camdesc* *cd1, Param* *pars1)
Da das wahrscheinlich hier nicht der Fall ist muss LabVIEW den entsprechenden Buffer bereitstellen.
Was den Inhalt der Struktur angeht, da können durchaus viele Nullen drin sein. Ich weiss ja nicht was da alles drinsteht aber warum den nicht auch Nullen?
Ob das Array nun U8 oder U32 ist macht nicht soviel aus. Die Struktur selber wird eh nicht alles U8 oder U32 enthalten und Du sagtest ja selber dass Du am Inhalt des Pointers selber nicht interessiert bist. Bei Verwendung von U8 musst Du einfach soviele Elemente allozieren als die Struktur in Bytes lang ist, bei Verwendung von U32 reicht es (Länge + 3 MOD 4) Elemente anzulegen.
|
|
|
16.12.2009, 15:47
Beitrag #7
|
ghostwhisperer
LVF-Grünschnabel
Beiträge: 12
Registriert seit: Mar 2007
2009
1998
de
70469
Deutschland
|
Einbinden externen Code mit unbekannter Parameterstruktur
Sorry hab mich wohl zu knapp ausgedrückt.
In einem hast recht, das sind Strukturen mit Ints, Strings, Arrays, weiteren Pointern usw drin.
Der generelle Programm-Ablauf soll zb so aussehen.
Int SR_API_Init (void) //Init der Kamera-Api
Int SR_API_SetupCam ( Camdesc* cd1, Param* pars1) // instanziert 1* Camdesc und 1*Parameter mit standardwerten Rückgabe sollen Pointer auf Instanzen sein
Int SR_API_StartCamConMan (Camdesc* cd1) // versucht Verbindung zur Kamera herzustellen, die im Camdescriptor beschrieben ist
Str SR_API_GETIP (Camdesc* cd1) // Beispiel: Kontrolle der IP der Kamera
...
INT SR_API_StopCamConMan (Camdesc* cd1) // schließt Kamera-Connection
Int SR_Api_Exit(void) // beendet Api
Mehr kann ich hier leider nicht sagen, da ich den Quellcode nicht hab. Der Programmierer der Firma ist sich eigentlich sicher, dass für die Ausführung aller Kamerafunktionen der Adresspointer auf den extern angelegten Speicherbereich für Camdesc ausreichend ist. Ich kriegs nur nicht in LabVIEW hin.
' schrieb:Also da ich nicht die ganze Headerdatei sehen kann muss ich hier natürlich Vermutungen machen aber die Deklaration
int LIBCALL SR_API_SetupCam ( Camdesc* cd1, Param* pars1)
lässt halt die Vermutung aufkommen dass es zwar ein Pointer ist aber eben nicht einer der von der DLL kommt. Das darum weil Camdesc und Param ziemlich sicher struct Deklarationen sind und nicht Pointer darauf. Also so was wie:
typedef struct {
sometype elm1;
sometype elm2;
.....
} Camdesc;
und nicht:
typedef struct {
sometype elm1;
sometype elm2;
.....
} *Camdesc;
Das heisst cd1 und pars1 sind zwar Pointer auf eine Struktur aber eben nicht Pointer die aus der DLL herauskommen. In C kann man nur Werte in einem Parameter zurückgeben indem man diesen Parameter als Referenz verwendet. Wenn die DLL also den Pointer zurückgeben wollte müsste der Pointer als Referenz übergeben werden was so aussehen würde:
int LIBCALL SR_API_SetupCam ( Camdesc* *cd1, Param* *pars1)
Da das wahrscheinlich hier nicht der Fall ist muss LabVIEW den entsprechenden Buffer bereitstellen.
Was den Inhalt der Struktur angeht, da können durchaus viele Nullen drin sein. Ich weiss ja nicht was da alles drinsteht aber warum den nicht auch Nullen?
Ob das Array nun U8 oder U32 ist macht nicht soviel aus. Die Struktur selber wird eh nicht alles U8 oder U32 enthalten und Du sagtest ja selber dass Du am Inhalt des Pointers selber nicht interessiert bist. Bei Verwendung von U8 musst Du einfach soviele Elemente allozieren als die Struktur in Bytes lang ist, bei Verwendung von U32 reicht es (Länge + 3 MOD 4) Elemente anzulegen.
|
|
|
17.12.2009, 09:00
Beitrag #9
|
IchSelbst
LVF-Guru
Beiträge: 3.689
Registriert seit: Feb 2005
11, 14, 15, 17, 18
-
DE
97437
Deutschland
|
Einbinden externen Code mit unbekannter Parameterstruktur
' schrieb:Mich interessiert weder der Aufbau des Handlers noch der Inhalt. Ich muss nur den Zeiger auf den Handler an die Funktionen zur Kamerasteuerung weitergeben könnnen.
Wenn ich das richtig interpretiere, bekommst du von der Funktion also lediglich zwei Pointer zurück. Man hätte - da es dich nicht interessiert, wie die jeweiligen Cluster ausfgebaut sind - den Prototypen auch machen können als "Int SR_API_SetupCam (int* MyIntVar1, int* MyIntVar2)". Wobei INT hier missbraucht wird als Zwischenspeicher für einen Pointer. Der Wert von MyIntVar2 interessiert dich überhaupt nicht. Lediglich MyIntVar1 musst du an die anderen Funktionen übergeben.
[*grübel*]
Für was brauchst du denn dann die DLL, wenn du nie Daten heraus liest ? Hat die ein eigenes "Frontpanel"?
[/*grübel*]
Sehe ich das richtig?
Wenn dem so ist, müsstest du lediglich im DLL-Knoten angeben: Typ UI32, Zeiger auf Wert. Für Int SR_API_SetupCam zweimal, für alle anderen einmal.
Jeder, der zur wahren Erkenntnis hindurchdringen will, muss den Berg Schwierigkeit alleine erklimmen (Helen Keller).
|
|
|
17.12.2009, 11:39
(Dieser Beitrag wurde zuletzt bearbeitet: 17.12.2009 11:55 von ghostwhisperer.)
|
ghostwhisperer
LVF-Grünschnabel
Beiträge: 12
Registriert seit: Mar 2007
2009
1998
de
70469
Deutschland
|
Einbinden externen Code mit unbekannter Parameterstruktur
Hallo !!
Richtich 2 Pointer. Die DLL umfasst alle Funktionen zur Kamerasteuerung, die ich brauche. Aber alle anderen Funktionen funzen erst, wenn der Handler einwandfrei ist. Diese SetupCam hat der Mann der Firma extra dafür geschrieben, dass ich die Riesenhandler für die Kamerasteuerung eben nicht selber in LV rekonstruieren muss. Müsste ich eigentlich um die anderen Funktionen überhaupt nutzen zu können.
Ich hab da noch ne Messkarte die ohne Probleme funktioniert. Ist ähnlich aufgebaut: importierte DLL-Funktionen. Hier ist es so, dass zB DIO_Config auch einen Handler instanziert aber nur das int "taskid" zurückgibt. Das ist, wenn ich das richtig verstehe, ein Pointer (also inhalt = speicheradresse) auf den Messkarten-Handler.
Hier steht aber, genau wie du auch grad grübelst, wirklich nur ein uint32 T *taskid, und eben nicht *structure (welcher Art auch immer) und das ganze als "Zeiger auf Wert". Genau prüfen kann ich das leider nicht, da ich hier nur die DLL hab und weder Header noch Quellcode.
Der Herr von Smartray meint nun Camdesc* cd1 gibt mir die Adresse raus.
Wenn ich das aber mit uint und zeiger auf Wert versuche geht gar nix.
Rolfk meint ja, dass cd1 und pars1 zwar Pointer auf eine Struktur sind aber eben nicht Pointer die aus der DLL herauskommen. Und in C kann man nur Werte in einem Parameter zurückgeben indem man diesen Parameter als Referenz verwendet.
Der Herr von Smartray hat entgegengesetzt gemeint, das wäre nicht so. Woher die Unstimmigkeit? Was gibt mir der Funktionsaufruf denn nun? Muss der so umgeschrieben werden, dass wirklich ein int bzw int* rauskommt? Kann ich die Kamerafunktionen dann denn noch ungeändert nutzen? die Erwarten ja *Camdesk und kein Int. Oder hat nur LabVIEW das Problem sowas wie Adressoperatoren usw eigentlich nicht zu kennen? Mit anderen Worten, angenommen ich krieg meinen uint32bitzeigerinhaltadresse aus der Setup, versteht der nächste Funktionsaufruf dessen Inhalt dann richtig ? Nämlich als Adresse der Instanz und eben nicht als einfachen Int und infolge als falschen Variablentyp.
Wenn das alles nicht gehen sollte.... Der Mann schreibt grad an der Api so rum, dass ich die Kamerafunktionen ganz ohne Handler nutzen kann. Der wird dann per ApiStart instanziert und verkapselt und im übrigen als globale Variable übergeben. Ich krieg dann einfach ne Schnittstelle zum Ändern oder Lesen von Inhalten des Handlers.
MFG Torsten
' schrieb:Wenn ich das richtig interpretiere, bekommst du von der Funktion also lediglich zwei Pointer zurück. Man hätte - da es dich nicht interessiert, wie die jeweiligen Cluster ausfgebaut sind - den Prototypen auch machen können als "Int SR_API_SetupCam (int* MyIntVar1, int* MyIntVar2)". Wobei INT hier missbraucht wird als Zwischenspeicher für einen Pointer. Der Wert von MyIntVar2 interessiert dich überhaupt nicht. Lediglich MyIntVar1 musst du an die anderen Funktionen übergeben.
[*grübel*]
Für was brauchst du denn dann die DLL, wenn du nie Daten heraus liest ? Hat die ein eigenes "Frontpanel"?
[/*grübel*]
Sehe ich das richtig?
Wenn dem so ist, müsstest du lediglich im DLL-Knoten angeben: Typ UI32, Zeiger auf Wert. Für Int SR_API_SetupCam zweimal, für alle anderen einmal.
|
|
|
| |