Dela via


Skapa ett objekt i COM

När en tråd har initierat COM-biblioteket är det säkert för tråden att använda COM-gränssnitt. Om du vill använda ett COM-gränssnitt skapar programmet först en instans av ett objekt som implementerar gränssnittet.

I allmänhet finns det två sätt att skapa ett COM-objekt:

  • Modulen som implementerar objektet kan tillhandahålla en funktion som är särskilt utformad för att skapa instanser av objektet.
  • Alternativt tillhandahåller COM en allmän skapandefunktion med namnet CoCreateInstance.

Ta till exempel det hypotetiska Shape objektet från ämnet Vad är ett COM-gränssnitt?. I det exemplet implementerar Shape-objektet ett gränssnitt med namnet IDrawable. Grafikbiblioteket som implementerar Shape-objektet kan exportera en funktion med följande signatur.

// Not an actual Windows function. 

HRESULT CreateShape(IDrawable** ppShape);

Med den här funktionen kan du skapa ett nytt Shape-objekt på följande sätt.

IDrawable *pShape;

HRESULT hr = CreateShape(&pShape);
if (SUCCEEDED(hr))
{
    // Use the Shape object.
}
else
{
    // An error occurred.
}

Parametern ppShape är av typen pekare till pekare tillIDrawable. Om du inte har sett det här mönstret tidigare kan den dubbla indirektionen vara förbryllande.

Överväg kraven för funktionen CreateShape. Funktionen måste ge en IDrawable pekare tillbaka till anroparen. Men funktionens returvärde används redan för fel-/framgångskoden. Pekaren måste därför returneras via ett argument till funktionen. Anroparen skickar en variabel av typen IDrawable* till funktionen och funktionen skriver över variabeln med en ny IDrawable pekare. I C++ finns det bara två sätt för en funktion att skriva över ett parametervärde: skicka efter referens eller skicka efter adress. COM använder den senare direktadressen. Och adressen till en pekare är en pekare till en pekare, så parametertypen måste vara av typen IDrawable**.

Här är ett diagram som hjälper dig att visualisera vad som händer.

diagram som visar pekardubbelindirektion

Funktionen CreateShape använder adressen till pShape (&pShape) för att skriva ett nytt pekarvärde för att pShape.

CoCreateInstance: Ett allmänt sätt att skapa objekt

Funktionen CoCreateInstance tillhandahåller en allmän mekanism för att skapa objekt. För att förstå CoCreateInstanceska du tänka på att två COM-objekt kan implementera samma gränssnitt och att ett objekt kan implementera två eller flera gränssnitt. Därför behöver en allmän funktion som skapar objekt två typer av information.

  • Vilket objekt som ska skapas.
  • Vilket gränssnitt som ska hämtas från objektet.

Men hur anger vi den här informationen när vi anropar funktionen? I COM identifieras ett objekt eller ett gränssnitt genom att tilldela det ett 128-bitarsnummer, kallat en globalt unik identifierare (GUID). GUID genereras på ett sätt som gör dem effektivt unika. GUID:er är en lösning på problemet med hur du skapar unika identifierare utan en central registreringsutfärdare. GUID kallas ibland universellt unika identifierare (UUID). Före COM användes de i DCE/RPC (Distributed Computing Environment/Remote Procedure Call). Det finns flera algoritmer för att skapa nya GUID:er. Inte alla dessa algoritmer garanterar absolut unikhet, men sannolikheten att oavsiktligt skapa samma GUID-värde två gånger är extremt liten – i praktiken noll. GUID:er kan användas för att identifiera alla typer av entiteter, inte bara objekt och gränssnitt. Det är dock den enda användning som berör oss i den här modulen.

Till exempel kan Shapes-biblioteket deklarera två GUID-konstanter:

extern const GUID CLSID_Shape;
extern const GUID IID_IDrawable; 

(Du kan anta att de faktiska 128-bitars numeriska värdena för dessa konstanter definieras någon annanstans.) Konstanten CLSID_Shape identifierar Shape-objektet, medan konstanten IID_IDrawable identifierar IDrawable-gränssnittet. Prefixet "CLSID" står för klassidentifierare, och prefixet IID står för gränssnittsidentifierare. Det här är vanliga namngivningskonventioner i COM.

Med dessa värden skapar du en ny Shape instans på följande sätt:

IDrawable *pShape;
hr = CoCreateInstance(CLSID_Shape, NULL, CLSCTX_INPROC_SERVER, IID_IDrawable,
     reinterpret_cast<void**>(&pShape));

if (SUCCEEDED(hr))
{
    // Use the Shape object.
}
else
{
    // An error occurred.
}

Funktionen CoCreateInstance har fem parametrar. De första och fjärde parametrarna är klassidentifieraren och gränssnittsidentifieraren. I själva verket säger dessa parametrar till funktionen "Skapa formobjektet och ge mig en pekare till IDrawable-gränssnittet".

Ange den andra parametern till NULL-. (Mer information om innebörden av den här parametern finns i avsnittet Aggregation i COM-dokumentationen.) Den tredje parametern tar en uppsättning flaggor vars huvudsakliga syfte är att ange körningskontext för objektet. Körningskontexten anger om objektet körs i samma process som programmet. i en annan process på samma dator. eller på en fjärrdator. I följande tabell visas de vanligaste värdena för den här parametern.

Flagga Beskrivning
CLSCTX_INPROC_SERVER Den samma processen.
CLSCTX_LOCAL_SERVER Olika processer, samma dator.
CLSCTX_REMOTE_SERVER Annan dator.
CLSCTX_ALL Använd det mest effektiva alternativet som objektet stöder. Rangordningen, från mest effektiv till minst effektiv, är: in-process, out-of-process och tvärdator.

 

Dokumentationen för en viss komponent kan tala om vilken körningskontext objektet stöder. Om inte använder du CLSCTX_ALL. Om du begär en körningskontext som objektet inte stöder returnerar funktionen CoCreateInstance felkoden REGDB_E_CLASSNOTREG. Den här felkoden kan också indikera att CLSID inte motsvarar någon komponent som är registrerad på användarens dator.

Den femte parametern till CoCreateInstance får en pekare till gränssnittet. Eftersom CoCreateInstance är en allmän mekanism kan den här parametern inte skrivas starkt. I stället är datatypen void**och anroparen måste tvinga pekarens adress till en void** typ. Det är syftet med reinterpret_cast i föregående exempel.

Det är viktigt att kontrollera returvärdet för CoCreateInstance. Om funktionen returnerar en felkod är COM-gränssnittspekaren ogiltig och försök att avreferera den kan orsaka att programmet kraschar.

Internt använder funktionen CoCreateInstance olika tekniker för att skapa ett objekt. I det enklaste fallet letar den upp klassidentifieraren i registret. Registerinmatningen pekar på en DLL eller EXE som implementerar objektet. CoCreateInstance- kan också använda information från en COM+-katalog eller ett SxS-manifest (sida vid sida). Oavsett är informationen transparent för anroparen. Mer information om de interna detaljerna i CoCreateInstancefinns i avsnittet COM-klienter och -servrar.

Det Shapes exempel som vi har använt är något intrikat, så nu ska vi gå till ett verkligt exempel på COM i praktiken: visa dialogrutan Öppna där användaren kan välja en fil.

Nästa

Exempel: Öppna dialogrutan