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!
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?
Jeder, der zur wahren Erkenntnis hindurchdringen will, muss den Berg Schwierigkeit alleine erklimmen (Helen Keller).
Anzeige
14.06.2016, 11:36 (Dieser Beitrag wurde zuletzt bearbeitet: 15.06.2016 09:24 von rolfk.)
(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.
(14.06.2016 11:36 )rolfk schrieb: Der Event Callback Knoten verlangt ein .Net Event.
Also gut: Dann heißt es nicht mehr Callback (im Sinne eines Funktionsaufrufes per spezifischen Delegate), sondern Event - im Sinne von "gemanagert von meinem Eventhandler". Für mich ergibt es dasselbe: Ich muss nicht pollen ...
Zitat: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
Hätte ja sein können ...
Zitat:Zwar besteht die Möglichkeit ...
Die Zeiten sind vorbei ... (in denen ich zugegeben sehr gut funktionierende "Sonderlösungen" entwickelt habe).
Zitat:Das heisst wenn die Versionen nicht genau stimmen ...
Du meinst die .Net-Versionen: Das hab ich mittlerweile auch herausgefunden. Muss ich also im Auge behalten ...
Fazit:
Dann muss der DLL-Hersteller ein Event verwenden bzw. zur Verfügung stellen. (Ich gehe davon aus, der kann das. Es hat ihm halt noch keiner gesagt, dass er für LV einen Event nehmen muss.)
Jeder, der zur wahren Erkenntnis hindurchdringen will, muss den Berg Schwierigkeit alleine erklimmen (Helen Keller).
15.06.2016, 09:39 (Dieser Beitrag wurde zuletzt bearbeitet: 15.06.2016 09:40 von rolfk.)
(14.06.2016 11:36 )rolfk schrieb: Der Event Callback Knoten verlangt ein .Net Event.
Also gut: Dann heißt es nicht mehr Callback (im Sinne eines Funktionsaufrufes per spezifischen Delegate), sondern Event - im Sinne von "gemanagert von meinem Eventhandler". Für mich ergibt es dasselbe: Ich muss nicht pollen.
Das ist sogar noch komplizierter als das. Ein Delegate ist ein Objectinterface das als Callback verwendet wird. Ein Funktionspointer, den Du da scheinbar hast, ist einfach ein Funktionspointer. Und dann sind da noch .Net Events! Alles möglich in .Net, wobei Funktionspointer für ein managed System wie .Net schon sehr archaisch sind und Delegates nur in C# wirklich funktionieren. Für Integration mit anderen dann C# Umgebungen sind .Net Events die am besten geeigneten, ausser Du verwendest C(++), dann ist der Funktionspointer das Einfachste.
Zitat:
Zitat:Das heisst wenn die Versionen nicht genau stimmen ...
Du meinst die .Net-Versionen: Das hab ich mittlerweile auch herausgefunden. Muss ich also im Auge behalten ...
Nö, ich meinte die Versionen von LabVIEW und der LabVIEW runtime. Wenn Deine DLL in derselben LabVIEW Version erstellt wurde dann die in der Du die DLL lädst, wird die DLL In-Process geladen und aufgerufen. Ansonsten lädt der DLL Wrapper die DLL Out-of-Process in einen LabVIEW Runtime Process und führt ihn mittels Datenmarshalling aus. Das heisst auch dass Du dann auf der Entwickelmaschine die LabVIEW Version in der Du entwickelst haben musst und die LabVIEW Runtime Version in der die DLL erstellt wurde. Und wenn Du dann die Applikation in ein Executable baust musst Du die Runtime Version Deiner Entwickelumgebung haben und die Runtime Version(en) in denen alle eventuellen DLLs erstellt wurden.
Das das Ganze mit den .Net Versionen noch einmal mindestens so kompliziert ist, macht es einfach noch spannender.
Zitat:Fazit:
Dann muss der DLL-Hersteller ein Event verwenden bzw. zur Verfügung stellen. (Ich gehe davon aus, der kann das. Es hat ihm halt noch keiner gesagt, dass er für LV einen Event nehmen muss.)
Nicht nur für LabVIEW! Zwar wird die letzte Version von Visual Basic inzwischen wohl auch irdendetwas haarsträubendes unterstützen um selbst Delegates benützen zu können, aber in der Vergangenheit musstest Du Events benützen oder Dich mit Funktionspointern herumschlagen und damit managed-to-unmanaged und zurück Schwierigkeiten in Kauf nehmen.
(15.06.2016 09:39 )rolfk schrieb: und Delegates nur in C# wirklich funktionieren.
Zitat:Zwar wird die letzte Version von Visual Basic inzwischen wohl auch irdendetwas haarsträubendes unterstützen um selbst Delegates benützen zu können
Zitat:Und wenn Du dann die Applikation in ein Executable baust musst Du die Runtime Version Deiner Entwickelumgebung haben und die Runtime Version(en) in denen alle eventuellen DLLs erstellt wurden.
Bisher konnten wir immer auf dem Rechner entwickeln (und den Endtest machen), der letztendlich der Arbeitsrechner wurde - dann sollte das ja klappen.
Jeder, der zur wahren Erkenntnis hindurchdringen will, muss den Berg Schwierigkeit alleine erklimmen (Helen Keller).
16.06.2016, 08:59 (Dieser Beitrag wurde zuletzt bearbeitet: 16.06.2016 09:10 von rolfk.)
(15.06.2016 09:39 )rolfk schrieb: und Delegates nur in C# wirklich funktionieren.
Zitat:Zwar wird die letzte Version von Visual Basic inzwischen wohl auch irdendetwas haarsträubendes unterstützen um selbst Delegates benützen zu können
Zitat:Und wenn Du dann die Applikation in ein Executable baust musst Du die Runtime Version Deiner Entwickelumgebung haben und die Runtime Version(en) in denen alle eventuellen DLLs erstellt wurden.
Bisher konnten wir immer auf dem Rechner entwickeln (und den Endtest machen), der letztendlich der Arbeitsrechner wurde - dann sollte das ja klappen.
Famous last words. Irgendwer hat mal gesagt: Niemand wird je mehr dann 640 kByte an Arbeitsspeicher in einem PC benötigen! Er ist zwar inzwischen einer der reichsten Leute auf der Erde, aber nicht wegen dieser Aussage.