Wie verwende ich eine COM-DLL mit LoadLibrary in C ++?

8

Erstens ist COM wie schwarze Magie für mich. Aber ich muss COM dll in einem Projekt verwenden, an dem ich arbeite.

Also, ich habe eine DLL, die ich entwickle, und ich brauche einige Funktionalitäten, die in einer separaten COM DLL verfügbar sind. Wenn ich mit Depends.exe auf die COM-DLL schaue, sehe ich Methoden wie DllGetClassObject () und andere Funktionen, aber keine der Funktionen, an denen ich interessiert bin.

Ich habe Zugriff auf den Quellcode der COM-DLL (Legacy), aber es ist ein Durcheinander und ich möchte lieber die COM-DLL im Binärformat verwenden, wie eine große Blackbox, die nicht weiß, was im Inneren vorgeht.

Also, wie kann ich die COM-DLL-Funktionen von meinem Code mit LoadLibrary aufrufen? Ist es möglich? Wenn, ja, könnten Sie mir ein Beispiel geben, wie es geht?

Ich verwende Visual Studio 6 für dieses Projekt.

Vielen Dank!

    
Etienne Savard 02.02.2010, 20:27
quelle

6 Antworten

11

Normalerweise würden Sie CoCreateInstance() verwenden, um ein Objekt aus einer COM DLL zu instanziieren. Wenn Sie dies tun, müssen Sie die DLL nicht zuerst laden und proc-Adressen erhalten, wie Sie es mit einer normalen DLL tun müssten. Dies liegt daran, dass Windows über die Typen, die eine COM-DLL implementiert, welche DLL sie implementiert und wie sie instanziiert werden, "weiß". (Angenommen natürlich, dass die COM-DLL registriert ist, was sie normalerweise ist).

Angenommen, Sie haben eine COM-DLL mit der IDog-Schnittstelle, die Sie verwenden möchten. In diesem Fall

dog.idl

%Vor%

myCode.cpp

%Vor%

All diese Speicherverwaltungs-Sachen können jedoch ziemlich grungy werden, und die ATL bietet intelligente Zeiger, die die Aufgabe der Instanziierung & amp; Verwalten Sie diese Objekte ein wenig einfacher:

%Vor%

BEARBEITEN:

Als ich das oben gesagt habe:

  

Windows "kennt" die Typen, die eine COM-DLL implementiert [... und]   In welcher DLL sind sie implementiert?

... Ich habe wirklich genau überlegt, wie Windows das weiß. Es ist keine Magie, obwohl es auf den ersten Blick etwas okkult erscheint.

COM-Bibliotheken enthalten Typbibliotheken, in denen die von der Bibliothek bereitgestellten Schnittstellen und CoClasses aufgeführt sind. Diese Typenbibliothek hat die Form einer Datei auf Ihrer Festplatte - sehr oft ist sie direkt in derselben DLL oder EXE wie die Bibliothek selbst eingebettet. Windows weiß, wo die Typbibliothek und die COM-Bibliothek selbst zu finden sind, indem sie in der Windows-Registrierung nachsehen. Einträge in der Registrierung sagen Windows, wo auf der Festplatte die DLL befindet.

Wenn Sie CoCreateInstance aufrufen, sucht Windows den clsid in der Windows-Registrierung nach, sucht die entsprechende DLL, lädt sie und führt den entsprechenden Code in der DLL aus, die das COM-Objekt implementiert.

Wie gelangen diese Informationen in die Windows-Registrierung? Wenn eine COM-DLL installiert ist, ist sie registriert. Dies geschieht in der Regel durch Ausführen von regsvr32.exe , die wiederum Ihre DLL in den Speicher lädt und eine Funktion mit dem Namen% co_de aufruft %. Diese Funktion, die in Ihrem COM-Server implementiert ist, fügt der Registrierung die erforderlichen Informationen hinzu. Wenn Sie ATL oder ein anderes COM-Framework verwenden, geschieht dies wahrscheinlich unter der Oberfläche, so dass Sie nicht direkt mit der Registry kommunizieren müssen. DllRegisterServer muss nur einmal zur Installationszeit aufgerufen werden.

Wenn Sie versuchen, DllRegisterServer für ein COM-Objekt aufzurufen, das noch nicht über den Prozess CoCreateInstance / regsvr32 registriert wurde, wird DllRegisterServer mit einem Fehler fehlschlagen, der besagt:

  

Klasse nicht registriert

Glücklicherweise ist die Lösung dafür, dass Sie einfach CoCreateInstance auf Ihrem COM-Server aufrufen und es dann erneut versuchen.

    
John Dibling 02.02.2010, 21:31
quelle
21

Im Allgemeinen sollten Sie CoCreateInstance oder CoGetClassObject anstatt direkt auf DllGetClassObject zuzugreifen. Aber Wenn Sie mit einer DLL arbeiten, die Sie nicht registrieren können oder wollen, beschreibt das Folgende (teilweise), was diese Funktion hinter den Kulissen tut.

Bei gegebener CLSID können Sie mit DllGetClassObject das Klassenobjekt ermitteln, von dem Sie Instanzen erstellen können (über die Schnittstelle IClassFactory , wenn ich mich richtig erinnere).

Zusammenfassung der Schritte (es ist eine Weile her, seit ich COM zum letzten Mal berührt habe, also bitte offensichtliche Fehler verzeihen):

  1. Rufen Sie DllGetClassObject(clsid, IID_IClassFactory, &cf) auf, wobei clsid die CLSID ist, für die Sie das Klassenobjekt erhalten möchten, und cf ist natürlich die Klassenfabrik.
  2. Rufen Sie cf->CreateInstance(0, iid, &obj) auf, wobei iid die IID der Schnittstelle ist, die Sie verwenden möchten, und obj ist natürlich das Objekt.
  3. ???
  4. Gewinn!

( CoCreateInstance führt die Schritte 1 und 2 aus. CoGetClassObject führt Schritt 1 aus. Sie würden CoGetClassObject verwenden, wenn Sie viele Instanzen derselben Klasse erstellen müssen, sodass Schritt 1 nicht jeweils wiederholt werden muss Zeit.)

    
Chris Jester-Young 02.02.2010 20:30
quelle
6

Sie verwenden LoadLibrary () nicht direkt mit einer COM-Bibliothek. CoCreateInstance () wird diese Funktion aufrufen, wenn sie noch nicht vorhanden ist, und dann eine Instanz der Klasse, die Sie in der Bibliothek implementiert haben, auf dem Heap neu anlegen und Ihnen schließlich einen unformatierten Zeiger auf das Objekt zurückgeben. Natürlich könnte es während des Prozesses fehlschlagen, und daher gibt es einen Mechanismus für Sie, um den Status wie HRESULT zu überprüfen.

Um es einfach zu benutzen, können Sie sich eine COM-Bibliothek als eine gewöhnliche DLL mit 1) vordefinierten (Haupt-) Funktionen vorstellen, 2) Sie müssen einige vordefinierte Funktionen wie CoCreateInstance () aufrufen, um sie einzugeben und zu akzeptieren dass es so ist, weil es muss.

    
t.g. 03.02.2010 02:45
quelle
3

Wenn die Typbibliothek in die DLL eingebettet ist, können Sie sie in Ihr Projekt importieren:

%Vor%

Dies generiert automatisch Header-Dateien, die in Ihrem Projekt enthalten sind und Ihnen die Verwendung der exportierten Objekte ermöglichen.

    
Luke 03.02.2010 04:40
quelle
1

Hier ist ein bisschen Code, der zeigt, wie man die Klassenfabrik bekommt und sie benutzt, um ein COM-Objekt zu erstellen. Es verwendet eine Struktur, um das Modul-Handle und den DllGetClassObject-Funktionszeiger zu verfolgen. Sie sollten die Modulkennung beibehalten, bis Sie mit dem COM-Objekt fertig sind.

Um diese Funktion zu verwenden, müssen Sie eine Instanz der ComModuleInfo-Struktur zuweisen und die szDLL auf den Dateinamen der DLL oder den vollständigen Pfadnamen festlegen. Rufen Sie dann die Funktion mit der Klassen-ID und der Schnittstellen-ID des COM-Objekts auf, das Sie von dieser DLL erhalten möchten.

%Vor%     
John Knoeller 02.02.2010 21:21
quelle
0

Wenn es sich um eine COM-DLL handelt, müssen Sie sie nur als Referenz zu Ihrem Projekt hinzufügen, und dann können Sie die Funktionen aufrufen, die in der DLL enthalten sind.

Ja, Sie können die Low-Level-COM-Funktionen wie DLLGetClassObject verwenden, aber warum sollten Sie?

    
Greg 02.02.2010 20:33
quelle

Tags und Links