360 likes | 487 Vues
COM-Schnittstellen optimal einsetzen Michael Willers mwillers@microsoft.com Microsoft GmbH. Agenda. Warum IDL? Wie funktioniert‘s? Wo gibt‘s weitere Info‘s?. Warum IDL?. Warum IDL?. Wie kann ich mit Visual C++... ...Felder an ASP-Scripts übergeben?
E N D
COM-Schnittstellen optimal einsetzen Michael Willersmwillers@microsoft.com Microsoft GmbH
Agenda • Warum IDL? • Wie funktioniert‘s? • Wo gibt‘s weitere Info‘s?
Warum IDL? • Wie kann ich mit Visual C++... • ...Felder an ASP-Scripts übergeben? • ...Datenstrukturen abbilden und verwenden? • ...Zeichenketten optimal einsetzen? • ...
Wie funktioniert‘s?Versionierung von Schnittstellen in VB • No compatibility • Sämtliche GUIDs werden neu erstellt • Typenbibliothek • CoKlassen (CLSID) • Schnittstellen (IID) • Project compatibility • VB5: CLSID und IID werden neu generiert • VB6: nur die IIDs werden neu generiert • Binary compatibility • Sämtliche GUIDs bleiben erhalten
Wie funktioniert‘s?Versionierung von Schnittstellen in VB • Die Auslieferung neuer Client- und Serverversionen erfolgt... • ...zusammen: Binary Compatibility reicht völlig aus • ...getrennt: Definieren Sie Ihre Schnittstellen direkt mit der IDL
Wie funktioniert‘s?Versionierung von Schnittstellen in VB • Ein mit VB6 erstellter Client ist grundsätzlich von der IID der Standardschnittstelle abhängig – egal ob er diese benutzt oder nicht!!! • Never use Project Compatibility!!!
Wie funktioniert‘s?Übergabe von Feldern an VB-Script • Felder werden grundsätzlich mit dem Typ SAFEARRAY abgebildet • In der IDL-Datei für Scripting Clients immer als VARIANT* deklarieren!!! • Feldelemente müssen grundsätzlich vom Typ VARIANT sein • Indexüberprüfung mit den Funktionen LBound oder Ubound klappt immer • Aber: „Type mismatch“ beim Elementzugriff
Wie funktioniert‘s?Aufzählungen (enums) und Strukturen • Mit dem Attribut v1_enum werden enum-Werte als 32bit-Werte interpretiert • sonst 16bit • Seit N4 SP4 kann der Universal Marshaler (OLEAUT32.DLL) auch mit Strukturen umgehen • Proxy/Stub-Marshaling nicht mehr notwendig • Windows 95 benötigt DCOM 1.2 oder höher • In allen Versionen von Windows 98 sowie Windows 2000 fest eingebaut
Wie funktioniert‘s?SAFEARRAYs mit Schnittstellenzeigern SAFEARRAY* SafeArrayCreateVectorEx( VARTYPE vt, // VT_UNKNOWN | FADF_HAVEIID UINT uLBound, UINT nSize, SAVEARRAYBOUND* psaBound, PVOID pvExtra /*pvExtra: IID* */ ); SAFEARRAY *psa; psa = SafeArrayCreateVectorEx( VT_UNKNOWN | FADF_HAVEIID, 0, 10, &IID_IMyInterface );
Wie funktioniert‘s?Schnittstellenzeiger • Schnittstellentyp zur Compilierzeit festlegen • HRESULT GetSth([out] ISth **ppISth); • Schnittstellentyp zur Laufzeit festlegen • HRESULT GetInterfacePtr( [in] REFIID riid, [out, iid_is(riid)] void **ppv );
Wie funktioniert‘s?Der Universal Marshaler • OLEAUT32.DLL enthält den Universal Marshaler, der Marshaling auf Basis von TypeLibraries durchführen kann • Schnittstellen in der TypeLibrary müssen das IDL-Attribut [dual] oder [oleautomation] aufweisen • TypeLibraries müssen auf Client UND Server registriert werden • REGTLIB.EXE (ruft RegisterTypeLib auf) • Parameter vom Methoden müssen “VARIANT-compliant” sein
Wie funktioniert‘s?Richtungsattribute für Parameter • [in] • Instanz wird vor Aufruf von Client zum Server übertragen • Client muss Instanz zerstören • implementierbar in VB (ByVal)
Wie funktioniert‘s?Richtungsattribute für Parameter • [out] • Instanz wird nach Aufruf von Server zum Client übertragen • Parametertyp muß ein Pointer sein • Server erzeugt Instanz • Client muß Instanz zerstören • nicht implementierbar in VB
Wie funktioniert‘s?Richtungsattribute für Parameter • [out, retval] • wie out, kann von Sprachen aber als Rückgabewert einer Funktion interpretiert werden • VB-Objektkatalog • muss letzter Parameter sein • implementierbar in VB
Wie funktioniert‘s?Richtungsattribute für Parameter • [in, out] • Instanz wird • vor Aufruf von Client zum Server übertragen • nach Aufruf von Server zum Client übertragen • sofern der Server andere Instanz zurückgibt, muss alte Instanz im Server zerstört und die zurückgegebene Instanz neu angelegt werden • Client muss Instanz zerstören • implementierbar in VB (ByRef)
Wie funktioniert‘s?CoTaskMemAlloc und CoTaskMemFree • referenzierter Speicher... • ...muß im Serverprozess mit CoTaskMemAlloc angelegt werden • ...wird im Serverprozess nach „Aufruf“ durch den Stub mit CoTaskMemFree zerstört • ...wird im Clientprozess nach „Rückkehr“ durch den Proxy mit CoTaskMemAlloc neu angelegt und initialisiert • muß im Clientprozess mit CoTaskMemFree zerstört werden
Wie funktioniert‘s?C-Arrays • [length_is] • Stub übertragt ausschliesslich Netto-Daten • Leere Feldelemente werden ignoriert • [size_is] • Feldgrösse wird zur Laufzeit bestimmt • Feldgrössen darf nur von [in] oder [in,out] Parametern abhängen
Wie funktioniert‘s?C-Arrays • [size_is(,10)] • Zeiger, der auf einen Zeiger verweist, der auf ein Feld mit 10 Elementen zeigt • [size_is(10,)] • Zeiger auf ein Feld mit 10 Zeigern HRESULT GetData3( [in, out] int* pnCount, [out, size_is(,*pnCount)] unsigned char** ppBuffer ); // **ppBuffer zeigt auf einen weiteren Zeiger *ppBuffer // *ppBuffer zeigt auf ein Feld mit (*pnCount) Elementen // vom Typ unsigned char
Wie funktioniert‘s?C-Strings • [string] • Variable vom Typ char* oder ein wchar_t* zeigt auf einen nullterminierten String • HRESULT F([in, string] char* psz); • Attribut bezieht sich immer auf den Zeiger, der char oder wchar_t referenziert • HRESULT F([out, string] char **ppsz);
Wie funktioniert‘s?Zeigerdatentypen • Problem 1: (&l1, &l2) • Dereferenzierte Daten müssen übertragen werden • Problem 2: f1(&l1, NULL) • Dereferenzieren des NULL Pointers • Problem 3: f1(&l1, &l1) • mehrfaches Dereferenzieren des gleichen Zeigers HRESULT f1([in, out] LONG* pl1, [in, out] LONG* pl2);
Wie funktioniert‘s?Zeigerdatentypen • Unique Pointers • IDL-Attribut [unique] • NULL-Pointer zulässig • mehrfach referenzierte Daten werden mehrfach übertragen • Default-Wert in ATL-Projekten • Ändern mit dem IDL-Attribut [pointer_default]
Wie funktioniert‘s?Zeigerdatentypen • Reference Pointers • IDL-Attribut [ref] • NULL-Pointer unzulässig • mehrfach referenzierte Daten werden mehrfach übertragen • zwingend für Parameter mit dem Attribut [out] und [out, retval] • Stub prüft auf Gültigkeit, somit werden unnötige Roundtrips eingespart!
Wie funktioniert‘s?Zeigerdatentypen • Full Pointers • IDL-Attribut [ptr] • NULL-Pointer zulässig • mehrfach referenzierte Daten werden nur einmal übertragen • Marshaling über Prozeßgrenzen hinweg wird durch die Überprüfung aller Zeiger auf Überschneidungen zeitaufwendiger • Attribut immer dann angeben, wenn zwei Zeiger auf den gleichen Speicherbereich verweisen • long l1; HESULT f1(&l1,&l1);
Wie funktioniert‘s?Proxy/Stub-Marshaling-Code generieren • Interface muß ausserhalb der Library Section stehen • Interface darf nicht Attribut [local] haben • MyFile_i.c, MyFile_p.c, dlldata.c kompilieren und linken • in ATL Projekten: NMAKE MyFilePS.mk • REGSVR32 MyFilePS.dll
Wie funktioniert‘s?C-Strings, C-Arrays, Zeiger-Strukturen • IDL-Attribute für Arrays und Strings werden nicht in TLB beschrieben • Proxy/Stub-Marshaling zwingend erforderlich • Proxy/Stub DLL muss erstellt und auf Client- und Server registriert werden • REGSVR32.EXE
Wie funktioniert‘s?Einschränkungen für Visual Basic • nur VB-kompatible Datentypen • keine C-Arrays • keine C-Strings • enum: ja • struct: ja, wenn Member keine Zeiger • keine [out] Parameter
Wo gibt’s weitere Info’s? • msdn online • http://www.microsoft.com/germany/msdn • TechTalk • www.microsoft.com/germany/msdn/techtalk • Bücher • COM IDL and Interface DesignISBN 1-86100-235-4 • Zeitschriften • Microsoft System Journal 6/99, Seite 85
Uff... Fragen!?