(09.06.2016 18:26 )IchSelbst schrieb: Hallo zusammen
Ich habe folgendes Problem und bräuchte ein paar Ratschläge:
Ich habe eine VB-.net-DLL vorliegen. Diese DLL arbeitet selbständig im Hintergrund und will mir, wenn sie mit Arbeiten fertig ist, per Callback Daten übermitteln.
Laut DLL-Hersteller muss ich die Funktion "Connect()" aufrufen unter anderem mit einen Parameter "Adress of Callback Function". Wenn ich gemeiner Weise die Funktion quasi mit NIL als Callback-Adresse aufrufe, kann ich (über andere Wege) sehen, dass die DLL an sich richtig arbeitet (- dumm nur dass der Callback fehlschlägt und LV sich komplett verabschiedet).
Es gibt einen Knoten Event-Callback auf der .NET-Palette. Allerdings ist es mir bisher nicht gelungen diesen Knoten irgendwie zu beschalten mit dem Ziel ein Wire zu bekommen, das an den Eingang "Adress of Callback Function" angebunden werden kann.
Meine Frage nun: Wie bekomme ich die Adresse eines VIs?
Kann es sein, dass der DLL-Hersteller einen Prototyp für den Callback zur Verfügung stellen muss und ich dann mein VI mit diesem Prototyp casten muss? - Oder wie geht das?
Gesetzt der Fall ich habe die Callback-Adresse erfolgreich übergeben: Werden auch in .NET Daten am Stack übergeben? Woher weis ich denn dann die Reihenfolge der Parameter in meinen VI?
Der Event Callback Knoten verlangt ein .Net Event. Eine .Net (und ActiveX) Komponente kann Events generieren und das ist eine spezielles Interface. Das ist also nicht einfach ein Callback Funktionspointer oder eine Klasse die ein bestimmtes Custom-Interface implementiert. Das was Du hast ist scheinbar ein Callback Funktionspointer und den musst Du in C(++), eventuel (#) implementieren.
LabVIEW VIs sind keine Funktionen im Sinne von C sondern eine komplet andere Spezies. Da kannst Du dann auch nicht einfach so einen Pointer drauf kriegen, denn die haben auch keinen Stack wie eine C Funktion. Parameter werden an ein VI über seine Connectorpane übergeben, was im Speicher eine komplete Datenstruktur ist.
Zwar besteht die Möglichkeit um von einem VI eine DLL zu machen in LabVIEW und die entsprechende Funktion dann mit LoadLibrary() und GetProcAddress() zu laden. Das geschieht indem der DLL Builder um jedes VI einen C Wrapper generiert der als C Funktion aufgerufen werden kann und dann die Funktionsparameter in eine entsprechende Datenstruktur packt und dann das VI in der LabVIEW Umgebung aufruft. Der entsprechende Funktionspointer von GetPRocAddress() könnte dann so verwendet werden, aber das ist eine auf längere Zeit wartungstechnisch völlig unbrauchbare Lösung. Erstens ist die entsprechende DLL bit-spezifisch, man muss also für 32 Bit und 64 Bit jeweils seperate DLLs machen, jeweils in der entsprechenden LabVIEW Variante und was noch viel schlimmer ist, die DLL läuft grundsätzlich in der LabVIEW Runtime Engine und in der Version die der LabVIEW Version entspricht in der die DLL erstellt wurde. Nur wenn die aktuelle Version der LabVIEW Entwickelumgebung genau übereinstimmt mit der Version in der die DLL erstellt wurde, schliesst LabVIEW das kurz und führt den DLL Code in der aufrufenden Engine aus.
Das heisst wenn die Versionen nicht genau stimmen (Unterschied in Bug fix level ist akzeptabel aber alles andere nicht) , dann läuft Deine DLL in einem anderen Prozess, dann Dein Hauptprogramm und muss alles zwischen den Prozessen über eine interprocesskompatible Schnittstelle (TCP/IP, Pipes, etc.) ausgetauscht werden. Für die Funktionsparameter macht der LabVIEW generierte Funktionswrapper in der DLL das für Dich aber eine Callbackfunktion will ja meist auch etwas direkt an Deine Applikation mitteilen und das musst Du dann irgendwie so implementieren dass es auch über Prozessgrenzen hinweg funktionieren bleibt.
Zwar scheint das am Beginn vielleicht noch kein Problem, da Du die DLL ja in der selben Version kompilierst in der Du die Applikation schreibst und kommst Du allenfalls ohne Interprocesskommunikation aus, aber wenn Du dann LabVIEW irgendwann upgradest, musst Du entweder die DLLs auch jedesmal neu kompilieren oder aber doch noch eine Interprocesskommunikation implementieren.