Behandeln von COM-Ereignissen in C ++ (ATL, MFC oder reines C ++) für Java-Interop

8

Ich versuche gerade, eine C ++ - Bibliothek (DLL-Datei) zu erstellen, die mit einer COM-Komponente verbunden ist, um sie in Java nutzbar zu machen. Die Idee war, dass ich eine sehr kleine C ++ - DLL mit einer Klasse erstellen würde, die die COM-Komponente umschließt und sie dann mit SWIG exportiert. Ich bin ziemlich weit gekommen, indem ich eine #import-Anweisung verwendet habe:

%Vor%

Und Aufruf von CoInitialize () und Erstellen einer Instanz der Komponente (über die IComponentNamePtr-Klasse, die von Visual Studio generiert wurde). Dies funktionierte für alle normalen COM-Methodenaufrufe, was gut war.

Ich kann jedoch nicht herausfinden, wie Ereignisse funktionieren. Ich sehe, dass es eine IComponentNameEventsPtr gibt, die die Hauptklasse "Smart Pointer" ergänzt, aber ich konnte nicht herausfinden, was zu tun ist, damit es funktioniert

Ich habe alle folgenden Schritte ausprobiert, um Ereignisse zum Laufen zu bringen:

  • Pure C ++ - Ich konnte nicht herausfinden, wie das geht. Ich habe versucht, eine neue Klasse zu erstellen, die von der IComponentNameEvents-Klasse geerbt hat, Stubs für alle abstrakten Funktionen erstellt und die Funktionen außer Kraft gesetzt hat, mit der Ausnahme, dass die Funktionen nicht als virtuell markiert sind, was nicht funktioniert.
  • MFC - Ich konnte den Aufruf von AfxOleInit nicht korrekt ausführen. Googling hat mir gesagt, dass der Aufruf fehlschlägt, wenn er von einer DLL aufgerufen wird, da er annimmt, dass OLE bereits initialisiert ist. Ich war mir nicht sicher, wie ich das beheben sollte. Meine Bibliothek stürzte jedes Mal ab, wenn ich versuchte, eine Instanz der COM-Komponente zu erstellen (ich nehme an, weil COM nicht richtig initialisiert wurde)
  • ATL - Ich konnte nicht herausfinden, wie ich die Events in ATL machen soll. Ich konnte die Klasse erstellen (über den Assistenten "Simple ATL" und dann den Assistenten "Implement Interface"), konnte aber nicht herausfinden, wie ich sie verwenden sollte. Ich habe mit IDispEventImpl in MSDN gelesen, konnte aber nicht herausfinden, wie ich die Klasse verwenden kann, die von diesem erzeugt wird wie man. Muss ich das COM-Objekt auch über ATL verwenden (oder kann ich die #import autogenerated Klassen verwenden)? Wie "anhefte" ich die Ereignis-Listener-Klasse?
  • Ich habe die Ereignisbehandlung in COM gelesen, in der das Attribut event_receiver (Teil des neuen Visual C ++ vereinheitlichtes Ereignismodell). Ursprünglich konnte ich nicht herausfinden, wie man das mit der Verwendung der COM-Komponente kombiniert, die mit der Anweisung #import erstellt wurde. Ich habe schließlich herausgefunden (und es wurde auf der Seite erwähnt!), Dass ich das Flag "embedded_idl" in der Anweisung #import verwenden muss, aber das hat andere Dinge kaputt gemacht (ich habe eine Reihe von Fehlern erwartet) die .tlh Datei)

Weiß jemand, wie man das macht? Was ist der einfachste Ansatz? Mein Hintergrund ist in C # und PHP, also habe ich nicht viel Erfahrung mit der Verwendung von COM in C ++.

tldr: Was ist der einfachste Weg, um COM-Ereignisse in einer C ++ - DLL zu verwenden?

    
Daniel Lo Nigro 14.04.2011, 10:25
quelle

2 Antworten

1

Ich habe das tatsächlich selbst mit dem Unified Event Model gemacht. Einige Notizen aus meiner Erfahrung, wie es funktioniert:

  • Sie müssen ATL initialisieren, andernfalls tritt beim Anhängen von Ereignissen ein Nullzeigerfehler auf. Wenn Sie nicht ATL in Ihrem Projekt verwenden möchten (wie ich nicht - Mein Projekt ist einfach C ++), funktioniert so etwas in dllmain.cpp (initialisiert ATL mit einem Dummy-Modul):

    %Vor%
  • Sie müssen "embedded_idl" am Ende der Zeile #import hinzufügen.

    %Vor%
  • Wenn die Komponente über eingebettete Strukturen verfügt, können Sie aufgrund eines Fehlers in Visual Studio einige MIDL2025-Fehler ("erwartet eine Typspezifikation nahe") erhalten (siehe Ссылка und Ссылка ). Lösung ist hinzuzufügen:

    %Vor%

Und fügen Sie dann ein

hinzu %Vor%

Für jede Struktur, die einen Fehler auslöst

  • Sobald dies erledigt ist, sollten Sie in der Lage sein, COM zu initialisieren und eine Instanz Ihres Objekts zu erstellen. Hässlicher Beispielcode:

    %Vor%

Sobald Sie Ihr COM-Objekt haben, können Sie Ereignisse gemäß dem MSDN-Artikel "Ereignisbehandlung in COM" verbinden:

%Vor%

Achten Sie darauf, alle Ereignisse vor dem Aufruf von CoUninitialize () abzuhaken, andernfalls erhalten Sie Fehler.

    
Daniel Lo Nigro 16.04.2011, 09:52
quelle
3

Implementieren Sie die Quellschnittstelle in Ihrem Code (unter Verwendung eines beliebigen Mechanismus, einschließlich der Generierung von einfachem C-Code mit dem Midl-Compiler). In Ihrer externen Typbibliothek (die, die Sie verbrauchen) Suchen Sie nach der Schnittstelle, die wie folgt aussieht:

%Vor%

Sobald Sie es implementiert haben, registrieren Sie es mit Advise für das Objekt, das die Ereignisse abruft (entfernen Sie die Registrierung mit Unadvise )

Hier ist ein Snippet, das eine typische Verwendung zeigt, vorausgesetzt, Sie haben den MIDL-Weg eingeschlagen (mit ATL / MFC müssten Sie weniger Code schreiben, aber mehr Makros / Templates)

%Vor%     
sehe 15.04.2011 09:05
quelle

Tags und Links