COM-biblioteket

Varje process som använder COM måste både initiera och avinitiera COM-biblioteket. Förutom att vara en specifikation implementerar COM även några viktiga tjänster i det här biblioteket. Com-biblioteket tillhandahålls som en uppsättning DLL:er och EXE :er (främst Ole32.dll och Rpcss.exe) i Microsoft Windows:

  • Ett litet antal grundläggande funktioner som underlättar skapandet av COM-program, både klient och server. För klienter tillhandahåller COM grundläggande funktioner för att skapa objekt. För servrar tillhandahåller COM ett sätt att exponera sina objekt.

  • Implementation-locator-tjänster genom vilka COM avgör, från en unik klassidentifierare (CLSID), vilken server som implementerar den klassen och var servern finns. Den här tjänsten innehåller stöd för en indirekt nivå, vanligtvis ett systemregister, mellan identiteten för en objektklass och paketeringen av implementeringen så att klienterna är oberoende av paketeringen, vilket kan ändras i framtiden.

  • Transparent fjärrprocedur anropar när ett objekt körs på en lokal server eller fjärrserver.

  • En standardmekanism som gör att ett program kan styra hur minne allokeras i processen, särskilt minne som måste skickas mellan samarbetsobjekt så att det kan frigöras korrekt.

Om du vill använda grundläggande COM-tjänster måste alla COM-körningstrådar i klienter och out-of-process-servrar anropa antingen funktionen CoInitialize eller CoInitializeEx innan du anropar någon annan COM-funktion förutom minnesallokeringsanrop. CoInitializeEx ersätter den andra funktionen och lägger till en parameter som gör att du kan ange trådmodellen för tråden: antingen lägenhetstrådad eller fritrådad. Ett anrop till CoInitialize anger helt enkelt trådmodellen till lägenhetstrådad.

OLE-sammansatta dokumentprogram anropar funktionen OleInitialize , som anropar CoInitializeEx och även gör viss initiering som krävs för sammansatta dokument. Därför kan trådar som anropar OleInitialize inte vara fritrådade. Information om trådning i klienter och servrar finns i Processer, Trådar och Lägenheter.

Processerver anropar inte initieringsfunktionerna eftersom de läses in i en process som redan har gjort det. Därför måste processerver ange sin trådmodell i registret under InprocServer32-nyckeln . Detaljerad information om problem med trådning i processinterna servrar finns i Problem med trådning i processinterna servrar.

Det är också viktigt att avinitialisera biblioteket. För varje anrop till CoInitialize eller CoInitializeEx måste det finnas ett motsvarande anrop till CoUninitialize. För varje anrop till OleInitialize måste det finnas ett motsvarande anrop till OleUninitialize.

Processerver kan förutsätta att processen som de läses in i redan har utfört de här stegen.

Important

Varje tråd som använder COM måste anropa CoInitializeEx innan någon annan COM-funktion anropas. Det här är det vanligaste com-initieringsfelet – att anropa CoCreateInstance eller andra COM-API:er på en tråd som inte har initierats misslyckas med CO_E_NOTINITIALIZED (0x800401F0).

Tip

Rekommenderat mönster – använd en RAII-vakt för att säkerställa avinitialisering:

#include <wil/com.h>  // Windows Implementation Libraries

// wil::unique_couninitialize_call calls CoUninitialize automatically on scope exit
auto comInit = wil::CoInitializeEx(COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);

// ... use COM — CoUninitialize is called when comInit goes out of scope,
//     even if an exception is thrown ...

Om wil inte är tillgängligt anropar du CoUninitialize() manuellt – varje lyckat CoInitializeEx anrop måste kopplas ihop med exakt ett CoUninitialize anrop:

HRESULT hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
if (FAILED(hr)) return hr;

// ... use COM ...

CoUninitialize();

Important

Vanliga misstag:

  • Anropa COM-funktioner utan att initiera COM i den aktuella tråden.
  • Anrop som CoInitializeEx / CoUninitialize inte stämmer överens (varje lyckad init kräver exakt en uninit).
  • Blandning av lägenhetsmodeller i samma tråd (samtal CoInitializeEx med en annan modell än ett tidigare lyckat anrop returnerar RPC_E_CHANGED_MODE).

Komponentobjektmodellen