- managed DLL mit COM-Interface am Beispiel: ComTest.dll (managed DLL in C#) und ComTestClient.exe (unmanaged C++ Exe)
- weiterführende Infos: Link
// Code für die ComTest.dll (managed Code) using System; using System.Runtime.InteropServices; // wichtig namespace ComTest { [ComVisible(true)] // wichtig [Guid("F3C44592-37E2-4a36-AABA-21527D3F750B")] // kann über Menü->Extras->GUID erstellen erzeugt werden // Interface-Klasse deklarieren public interface IClass1 { int Add(int i1, int i2); int Sub(int i1, int i2); string AddString(string sZeichenfolge); } [ClassInterface(ClassInterfaceType.AutoDispatch)] // wichtig public class Class1: IClass1 { public int Add(int i1, int i2) { return i1 + i2; } public int Sub(int i1, int i2) { return i1 - i2; } public string AddString(string sZeichenfolge) { return sZeichenfolge + " " + sZeichenfolge; } } }
- Projekt->Eigenschaften->Anwendung->Assemblyinformationen->Haken bei “Assembly COM-sichbar machen”
- Projekt->Eigenschaften->Erstellen->Haken bei “Für COM-Interop registrieren”
- DLL kompilieren -> ComTest.dll und ComTest.tlb (Interfaceinformationen) werden erstellt
- Soll die DLL auf einem anderen Rechner eingesetzt werden, müssen dort die Interfaceklassen unbedingt mit “RegAsm.exe ComTest.dll /codebase” registriert werden.
- ComTest.tlb und ComTest.dll in das Quellverzeichnis der ComTestClient.exe kopieren, bei Veränderungen am Quellcode der DLL diesen Vorgang wiederholen 🙂
// ComTestClient.exe (unmanaged Code mit COM-Interface) #include "stdafx.h" #import "ComTest.tlb" no_namespace //TLB mit Interface und Funktionen der ComTest.dll importieren int _tmain(int argc, _TCHAR* argv[]) { long iRes=0; HRESULT hr = ::CoInitialize (NULL); if (hr == S_OK) { // Zeiger auf lokales COM-Objekt der Klasse Class1 holen IClass1Ptr pClass1 (__uuidof(Class1)); // Funktion Add() aufrufen if (pClass1) { long i = pClass1->Add(1, 5); pClass1->Release(); } } ::CoUninitialize(); return 0; }
- Eine zweite Möglichkeit ein COM-Objekt zu erstellen wird über CoCreateInstance() ermöglicht.
- Der Vorteil dabei ist, dass man einen global verwendbaren Zeiger erhält.
// ComTestClient.exe (unmanaged Code mit COM-Interface) #include "stdafx.h" #import "ComTest.tlb" no_namespace //TLB mit Interface und Funktionen der ComTest.dll importieren int _tmain(int argc, _TCHAR* argv[]) { long iRes=0; IClass1 * pInterfacePtr = NULL; // Zeiger auf das Interface HRESULT hr = ::CoInitialize (NULL); if (hr == S_OK) { if (SUCCEEDED(CoCreateInstance(__uuidof(Class1), NULL, CLSCTX_ALL, __uuidof(IClass1), (LPVOID *)&pInterfacePtr))) { if (pInterfacePtr) { // Add aufrufen long i = pInterfacePtr->Add(1, 5); pInterfacePtr->Release(); } } } ::CoUninitialize(); return 0; }
- Will man ein COM-Objekt aus einer managed DLL innerhalb einer unmanaged DLL benutzen, darf die verwaltete Ausführung (__uuidof(Class1)) nicht in der DLLMain() [InitInstance(), ExitInstance()] stattfinden, sondern nur innerhalb einer selber geschriebenen DLL-Funktion. Es kommt sonst zur Auslösung eines Haltepunktes und die Anwendung friert ein.
- Folgender Meldungstext wird dann im Ausgabefenster von VS angezeigt: