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!
15.01.2007, 10:36 (Dieser Beitrag wurde zuletzt bearbeitet: 15.01.2007 10:38 von Semtex.)
Ich bin zwar schon seit einigen Jahren in Kontakt mit LabVIEW, jedoch beginn ich erst jetzt mich näher damit zu befassen.
Jetzt ist ein Problem aufgetretten das ich selbst nicht lösen kann, deshalb würde ich mich freuen wenn mir jemand von euch helfen würde. Und zwar folgendes:
Ich habe eine DLL (welche ich nicht ändern kann), und will jetzt folgendes Unterprogamm aufrufen:
Return-Wert ist kein problem, U32
hDevice bekomm ich auch ohne Probleme hinein
Jedoch machen mit _BUFFER_ST und LPOVERLAPPED Sorgen:
typedef struct
{
SHORT *pBuffer; // Pointer to buffer
UINT size; // Buffersize in bytes: max. 1024 bytes
UINT validPoints; // number of data points returned from driver
}_BUFFER_ST;
size ist unsingend INT (32bit) und validPoints das selbe Jedoch wissen wir nicht wie wir in LabVIEW einen Buffer erstellen bzw. den Zeiger darauf bekommen!
Auf jeden Fall bekommen wir als Rückgabewert nur 0 (false) bzw. 1 (aufruf erfolgreich) zurück, das heißt der Buffer muss sich selbst IRGENDWIE auffüllen (oi...) Daher die Frage:Wie erstelle ich einen Buffer und mache einen Zeiger darauf?
Also da wird der Zeiger auf LPOVERLAPPED übergeben, da hab ich echt KEINE AHNUNG wie das funktioniert. Vom C-File kann ich nur eines sagen.
hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
ov.hEvent = hEvent;
ov.Offset = 0;
ov.OffsetHigh = 0;
Ob ich jetzt alle Elemente der Struktur einzeln übergeben muss oder nicht weiß ich ebenfalls nicht.
Also in einem anderen Beitrag habe ich gelesen das man die Strukturen einzelnd übergeben muss / kann, also z.b.:
typedef struct _OVERLAPPED {
DWORD Internal;
DWORD InternalHigh;
DWORD Offset;
DWORD OffsetHigh;
HANDLE hEvent;
} OVERLAPPED, *LPOVERLAPPED;
wird zu 5 Eingängen in die DLL, 4*32bi Unsignend
Was ist z.B. HANDLE?
unsigned long GT_GetData(long hDevice, unsigned short int *pBuffer, unsigned long size, unsigned long validPoints, unsigned long Internal, long InternalHigh, long Offset, long OffsetHigh, long hEvent);
so dachte ich das es IRGENDWIE gehen sollte. Jedoch weißt ich nicht was hEvent ist und mit dem Zeiger auf das 1. Element des Buffers habe ich auch noch so meine Probleme. Das ist ein 16 bit Zeiger der auf ein Array mit 512 Dimensionen zeigt oder!?
Bin für Verbesserungsvorschläge (es geht so nicht) immer offen
' schrieb:Also in einem anderen Beitrag habe ich gelesen das man die Strukturen einzelnd übergeben muss / kann,
Richtig: In jenem Falle "kann". Aber auch nur deswegen, weil in der Parameterliste nix mit * steht (guckst du dort Posting #9: BOOL __stdcall Unterprogramm(HANDLE handle1,_AIN Analog,_DIO Digital); ). In deinem Falle geht (vorerst) garnichts. Wenn da ein * steht, ist das tatsächlich ein Pointer, der - so wie in diesem Falle - zum Schreiben benutzt wird. Das einzige, das du (vorerst) machen kannst, ist für _OVERLAPPED Null (nummerisch Null in U32) zu übergeben. (Nicht überall, wo die Möglichkeit besteht eine Overlapped-Struktur zu benutzen, wird sie auch zwangsweise benutzt).
Zitat:Was ist z.B. HANDLE?
HANDLE ist spezieller Typ und entspricht einem U32-Wert. Ein Handle ist immer ein Pointer und zwar ein solcher mit speziellen "Funktionen". Ein Handle - na guckst du lieber WikiPedia.
Zitat:mit dem Zeiger auf das 1. Element des Buffers habe ich auch noch so meine Probleme. Das ist ein 16 bit Zeiger der auf ein Array mit 512 Dimensionen zeigt oder!?
Jowohl.
Short int ist zwar die LV-Bezeichnung für ein U16/I16. Allerdings glaube ich, dass in C++ short int eher U8/I8 ist. Das Array hat nicht 512 Dimmensionen - sondern eine mit 512 (bzw. 1024) Werten. Als Übergabetyp kommt hier auf jeden Fall Array-Datenzeiger in Frage. Ob "Short Int" oder "Byte"/"Char" ist egal. (Ob die Übergabe eines Structs in der Art wie _BUFFER_ST geht, weis ich noch nicht)
Zitat:Bin für Verbesserungsvorschläge (es geht so nicht) immer offen
Ich bin ja der Meinung, das wird nix - irgendwo hat jedes System eine Grenze. Zumindest das mit dem Overlapped wird in LV eher schwierig.
Jeder, der zur wahren Erkenntnis hindurchdringen will, muss den Berg Schwierigkeit alleine erklimmen (Helen Keller).
29.01.2007, 10:25 (Dieser Beitrag wurde zuletzt bearbeitet: 29.01.2007 11:13 von Semtex.)
' schrieb:Das Array hat nicht 512 Dimmensionen - sondern eine mit 512 (bzw. 1024) Werten. Als Übergabetyp kommt hier auf jeden Fall Array-Datenzeiger in Frage. Ob "Short Int" oder "Byte"/"Char" ist egal. (Ob die Übergabe eines Structs in der Art wie _BUFFER_ST geht, weis ich noch nicht)
Ich bin ja der Meinung, das wird nix - irgendwo hat jedes System eine Grenze. Zumindest das mit dem Overlapped wird in LV eher schwierig.
Tja, das wär doch einmal eine Frage wert: Wie erstelle ich ein 1D-Array mit 512 Werten (Elementen) in LabVIEW 7.20?`
Eines ist mir auch aufgefallen: Ich habe Probleme damit die ganzen examples die hier zu finden sind zu öffnen weil ich schlicht weg kein 8.20 habe und die Versionen nicht kompatibel sind...
Hier mal der Funktionsprototyp:
unsigned long up(long hDevice, unsigned short int *pBuffer, unsigned long size, unsigned long validPoints, unsigned long *lpoverlapped);
*lpoverlapped habe ich einmal als 0 angenohmen
*pBuffer ist ein Zeiger auf ein 1D-Array. Ich gebe einfach mal nen Screenshot rein: (die obere Leitung passt schon, keine Sorge)
Zusätzlich habe ich noch unsere nette Fehlermeldung hochgeladen (wuhu, wenigstens hängt sich LabVIEW nicht mehr permanent auf!!!)
' schrieb:Tja, das wär doch einmal eine Frage wert: Wie erstelle ich ein 1D-Array mit 512 Werten (Elementen) in LabVIEW 7.20?
Wie in allen anderen LV-Versionen auch: Array-Palette>Array initialisieren. Dabei ist zu beachten, dass als Array-Element ein UInt16 notwendig ist.
Zitat:Eines ist mir auch aufgefallen: Ich habe Probleme damit die ganzen examples die hier zu finden sind zu öffnen weil ich schlicht weg kein 8.20 habe und die Versionen nicht kompatibel sind...
Dann beschwer' dich bei NI.
Zitat:Hier mal der Funktionsprototyp:
unsigned long up(long hDevice, unsigned short int *pBuffer, unsigned long size, unsigned long validPoints, unsigned long *lpoverlapped);
Jetzt zeigt du noch den von LV erzeugten Funktionsprototyp, dann kann ich genauer kucken.
Zitat:*lpoverlapped habe ich einmal als 0 angenohmen
Schließ mal an den Ausgang, der zu diesem Eingnag gehört, ein Anzeigeelement an.
Zitat:*pBuffer ist ein Zeiger auf ein 1D-Array.
Ich hoffe doch: Zeiger auf Wert UInt16
Zitat:Zusätzlich habe ich noch unsere nette Fehlermeldung hochgeladen (wuhu, wenigstens hängt sich LabVIEW nicht mehr permanent auf!!!)
Ich gehe mal davon aus, dass die DLL so intelligent ist keinen Fehler zu machen, wenn validPoints Null ist. Im schlimmsten Falle liegt das an dem LPOverlapped. LPOverlapped ist ein Pointer auf eine Struktur. Und das ist in LV nur schwer möglich (wie, weis ich aber noch nicht) oder eben auch gar nicht. Und wenn die DLL den Pointer respektive der Speicher, auf den der Pointer zeigt, benötigt - dann sehe ich schwarz.
Ansonsten sieht der DLL-Knoten nicht schlecht aus.
Jeder, der zur wahren Erkenntnis hindurchdringen will, muss den Berg Schwierigkeit alleine erklimmen (Helen Keller).
' schrieb:Jetzt zeigt du noch den von LV erzeugten Funktionsprototyp, dann kann ich genauer kucken.
Habe ich schon oben gepostet:
unsigned long GT_GetData(long hDevice, unsigned short int *pBuffer, unsigned long size, long validPoints, unsigned long *lpOvl);
' schrieb:Schließ mal an den Ausgang, der zu diesem Eingnag gehört, ein Anzeigeelement an.
Hab ich gemacht, da aber die DLL nicht richtig ausgeführt wurde (siehe Fehlermeldung oben) bekomme ich nichts raus.
Zitat:Hab ich gemacht, da aber die DLL nicht richtig ausgeführt wurde (siehe Fehlermeldung oben) bekomme ich nichts raus.
Gut. Jetzt setzt du noch auf den Draht zum Anzeigeelement einen Breakpoint - und sagst Bescheid, ob der Breakpoint ausgeführt wird oder ob wieder die Fehlermeldung kommt.
Es scheint also tatsächlich so, dass die DLL gerne einen richtig funktionierenden *lpOverlapped haben möchte. Da wird mir wohl nichts anderes übrig bleiben - als mir was einfallen zu lassen.
Im übrigen: Du hast doch wohl die richtige Aufrufkonvention gewählt? StdCall?
Und noch eins:
Probier mal folgendes aus: Besetzte das Array nicht mit Nullen vor, sondern mit Einsen. Außerdem übergibst du 100 ValidPoints (anstelle von 0) und Size=200 (anstelle von 0).
Was soll denn die DLL überhaupt machen?
Jetzt hab' ich mir den Thread noch mal angekuckt - und bin auf folgende Inkonsistenz gestoßen. Im ersten Posting schreibst du, die DLL-Funktion sieht so "BOOL UP(HANDLE hDevice,_BUFFER_ST *buffer,LPOVERLAPPED lpOvl);" aus. Das sind drei Parameter auf dem Stack. Erzeugt hast du aber eine solche Funktion: "unsigned long up(long hDevice, unsigned short int *pBuffer, unsigned long size, unsigned long validPoints, unsigned long *lpoverlapped);". Das sind aber fünf Parameter auf dem Stack. Fünf und drei beißt sich aber - und führt garantiert zu einer AccessViolation.
Es wird dir gar nichts anderes übrigbleiben als zu warten, bis mir (oder dir oder jemand anderem) eine passende Lösung eingefallen ist.
Jeder, der zur wahren Erkenntnis hindurchdringen will, muss den Berg Schwierigkeit alleine erklimmen (Helen Keller).
' schrieb:Gut. Jetzt setzt du noch auf den Draht zum Anzeigeelement einen Breakpoint - und sagst Bescheid, ob der Breakpoint ausgeführt wird oder ob wieder die Fehlermeldung kommt.
Nein er wird nicht ausgeführt sondern die Fehlermeldung kommt.
' schrieb:Im übrigen: Du hast doch wohl die richtige Aufrufkonvention gewählt? StdCall?
Jop die passt! Funktioniert schon bei den anderen DLLs die ich eingebunden habe.
' schrieb:Und noch eins:
Probier mal folgendes aus: Besetzte das Array nicht mit Nullen vor, sondern mit Einsen. Außerdem übergibst du 100 ValidPoints (anstelle von 0) und Size=200 (anstelle von 0).
Hmm, lustige Idee *g* aber trotzdem gibts ne Fehlermeldung.
' schrieb:Was soll denn die DLL überhaupt machen?
Also wenn ich unserem Arbeitsgeber sowie unserem Projektleiter glauben kann folgendes:
Zuvor aufgerufene DLLs initialisieren eine Hardware. Diese Hardware schickt uns integerwerte zurück. Laut unserem Projektleiter ist es so das wir der DLL den Zeiger auf einen Buffer (array mit 512 Elementen) übergeben, und als "Ausgang" werden diese 512 Elemente gefüllt. Ich hoffe du kannst dir unter dieser Erklärung was vorstellen.
' schrieb:Jetzt hab' ich mir den Thread noch mal angekuckt - und bin auf folgende Inkonsistenz gestoßen. Im ersten Posting schreibst du, die DLL-Funktion sieht so "BOOL UP(HANDLE hDevice,_BUFFER_ST *buffer,LPOVERLAPPED lpOvl);" aus. Das sind drei Parameter auf dem Stack. Erzeugt hast du aber eine solche Funktion: "unsigned long up(long hDevice, unsigned short int *pBuffer, unsigned long size, unsigned long validPoints, unsigned long *lpoverlapped);". Das sind aber fünf Parameter auf dem Stack. Fünf und drei beißt sich aber - und führt garantiert zu einer AccessViolation.
Das liegt daran:
GT_GetData(HANDLE hDevice,_BUFFER_ST *buffer,LPOVERLAPPED lpOvl);
Das ist der C-Aufruf
hDevice ist 1 Wert
lpOvl wissen wir nicht, haben wir vorerst auch als 1 Wert (0) angegeben
*buffer ist eine Struktur:
typedef struct // structure used to handle buffers
{
SHORT *pBuffer; // Pointer to buffer
UINT size; // Buffersize in bytes: max. 1024 bytes
UINT validPoints; // number of data points returned from driver
}_BUFFER_ST; // (data point size is 2 bytes)
deswegen hätte ich gesagt muss man 3 Werte dafür übergeben
___________________________ Unterm Strich
1+1+3 = 5
Ausprobiert haben wir auch schon das wir für lpOvl alle in der Struktur enthaltene Werte (4*DWORD + hEvent) eigens übergeben, jedoch tritt dann das Problem mit hEvent auf...
' schrieb:Es wird dir gar nichts anderes übrigbleiben als zu warten, bis mir (oder dir oder jemand anderem) eine passende Lösung eingefallen ist.
Tja, ich hoffe dir geht es nicht wie mir und du bist mit deinem Latein am Ende *g* Vielen Dank für alles bis jetzt. Falls du einen Geistesblitz hast würde es mich freuen *g*
Hinweis:
Das ist keine lustige Idee, das ist ein Verfahren zum Fehlereingrenzen.
Zitat:deswegen hätte ich gesagt muss man 3 Werte dafür übergeben
Ich bin noch immer der Meinung, dass das so nicht gehen wird.
Und jetzt das ganze ohne Diplomatie: Das kannst du dir abschminken. Das wird nichts. Das ist nicht kompatibel. Du kannst nicht einfach einen Pointer auf eine Struktur durch die Struktur ersetzen. Wenn die DLL einen Pointer erwartet - UND DAS TUT SIE - musst du ihr einen geben. Du kannst von Glück reden, dass dieses dein Vorgehen, was programmtechnisch total neben der Kappe ist, soweit daneben ist, dass eine AccessViolation auftritt - Nicht bei jedem "Programmierfehler" würde es zu einer AccessVialation kommen.
Zitat:Tja, ich hoffe dir geht es nicht wie mir und du bist mit deinem Latein am Ende
Ich nicht.:cool:Ich kann DLLs schreiben.
Jeder, der zur wahren Erkenntnis hindurchdringen will, muss den Berg Schwierigkeit alleine erklimmen (Helen Keller).