Compartir a través de


Crear un objeto en COM

Una vez que un subproceso ha inicializado la biblioteca COM, es seguro que el subproceso use interfaces COM. Para usar una interfaz COM, el programa crea primero una instancia de un objeto que implementa esa interfaz.

En general, hay dos maneras de crear un objeto COM:

  • El módulo que implementa el objeto puede proporcionar una función diseñada específicamente para crear instancias de ese objeto.
  • Como alternativa, COM proporciona una función de creación genérica denominada CoCreateInstance.

Por ejemplo, tome el objeto hipotético Shape del tema ¿Qué es una interfaz COM?. En ese ejemplo, el Shape objeto implementa una interfaz denominada IDrawable. La biblioteca de gráficos que implementa el Shape objeto podría exportar una función con la siguiente firma.

// Not an actual Windows function. 

HRESULT CreateShape(IDrawable** ppShape);

Dada esta función, puede crear un nuevo Shape objeto como se indica a continuación.

IDrawable *pShape;

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

El parámetro ppShape es de tipo pointer to-pointer-to-IDrawable. Si no ha visto este patrón antes, es posible que el doble direccionamiento indirecto sea desconcertante.

Tenga en cuenta los requisitos de la CreateShape función. La función debe devolver un IDrawable puntero al autor de la llamada. Pero el valor devuelto de la función ya se usa para el código de error o correcto. Por lo tanto, el puntero debe devolverse a través de un argumento a la función . El autor de la llamada pasará una variable de tipo IDrawable* a la función y la función sobrescribirá esta variable con un nuevo IDrawable puntero. En C++, solo hay dos maneras de que una función sobrescriba un valor de parámetro: pasar por referencia o pasar por dirección. COM usa la última dirección de paso a paso. Y la dirección de un puntero es un puntero a un puntero, por lo que el tipo de parámetro debe ser IDrawable**.

Este es un diagrama para ayudar a visualizar lo que está ocurriendo.

diagrama que muestra el direccionamiento indirecto de puntero doble

La CreateShape función usa la dirección de pShape (&pShape) para escribir un nuevo valor de puntero en pShape.

CoCreateInstance: una manera genérica de crear objetos

La función CoCreateInstance proporciona un mecanismo genérico para crear objetos. Para comprender CoCreateInstance, tenga en cuenta que dos objetos COM pueden implementar la misma interfaz y un objeto puede implementar dos o más interfaces. Por lo tanto, una función genérica que crea objetos necesita dos fragmentos de información.

  • Objeto que se va a crear.
  • Interfaz que se va a obtener del objeto .

¿Pero cómo se indica esta información cuando llamamos a la función? En COM, un objeto o una interfaz se identifica asignando un número de 128 bits, denominado identificador único global (GUID). Los GUID se generan de forma que los convierten en únicos de forma eficaz. Los GUID son una solución al problema de cómo crear identificadores únicos sin una entidad de registro central. A veces, los GUID se denominan identificadores únicos universales (UUID). Antes de COM, se usaban en DCE/RPC (entorno informático distribuido/llamada a procedimiento remoto). Existen varios algoritmos para crear nuevos GUID. No todos estos algoritmos garantizan estrictamente la unicidad, pero la probabilidad de crear accidentalmente el mismo valor GUID dos veces es extremadamente pequeña, efectivamente cero. Los GUID se pueden usar para identificar cualquier tipo de entidad, no solo objetos e interfaces. Sin embargo, ese es el único uso que nos preocupa en este módulo.

Por ejemplo, la Shapes biblioteca puede declarar dos constantes GUID:

extern const GUID CLSID_Shape;
extern const GUID IID_IDrawable; 

(Puede suponer que los valores numéricos reales de 128 bits para estas constantes se definen en otro lugar). La constante CLSID_Shape identifica el Shape objeto, mientras que la constante IID_IDrawable identifica la IDrawable interfaz. El prefijo "CLSID" significa identificador de clase y el prefijo IID significa identificador de interfaz. Se trata de convenciones de nomenclatura estándar en COM.

Dados estos valores, crearía una nueva Shape instancia de la siguiente manera:

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.
}

La función CoCreateInstance tiene cinco parámetros. Los primeros y cuartos parámetros son el identificador de clase y el identificador de interfaz. En efecto, estos parámetros indican a la función "Crear el objeto Shape y dame un puntero a la interfaz IDrawable".

Establezca el segundo parámetro en NULL. (Para obtener más información sobre el significado de este parámetro, vea el tema Agregación en la documentación de COM). El tercer parámetro toma un conjunto de marcas cuyo propósito principal es especificar el contexto de ejecución para el objeto. El contexto de ejecución especifica si el objeto se ejecuta en el mismo proceso que la aplicación; en un proceso diferente en el mismo equipo; o en un equipo remoto. En la tabla siguiente se muestran los valores más comunes para este parámetro.

Marca Descripción
CLSCTX_INPROC_SERVER Mismo proceso.
CLSCTX_LOCAL_SERVER Proceso diferente, mismo equipo.
CLSCTX_REMOTE_SERVER Equipo diferente.
CLSCTX_ALL Utilice la opción más eficaz que admite el objeto. (La clasificación, de la más eficaz a la menos eficiente, es: en proceso, fuera de proceso y entre equipos).

 

La documentación de un componente determinado puede indicarle qué contexto de ejecución admite el objeto. Si no es así, use CLSCTX_ALL. Si solicita un contexto de ejecución que el objeto no admite, la función CoCreateInstance devuelve el código de error REGDB_E_CLASSNOTREG. Este código de error también puede indicar que el CLSID no corresponde a ningún componente registrado en el equipo del usuario.

El quinto parámetro de CoCreateInstance recibe un puntero a la interfaz. Dado que CoCreateInstance es un mecanismo genérico, este parámetro no se puede escribir fuertemente. En su lugar, el tipo de datos es void**, y el autor de la llamada debe convertir la dirección del puntero en un tipo void** . Ese es el propósito del reinterpret_cast en el ejemplo anterior.

Es fundamental comprobar el valor devuelto de CoCreateInstance. Si la función devuelve un código de error, el puntero de la interfaz COM no es válido e intentar desreferenciarlo puede provocar que el programa se bloquee.

Internamente, la función CoCreateInstance usa varias técnicas para crear un objeto. En el caso más sencillo, busca el identificador de clase en el Registro. La entrada del Registro apunta a un archivo DLL o EXE que implementa el objeto . CoCreateInstance también puede usar información de un catálogo COM+ o un manifiesto en paralelo (SxS). Independientemente de, los detalles son transparentes para el autor de la llamada. Para obtener más información sobre los detalles internos de CoCreateInstance, vea Clientes y servidores COM.

El Shapes ejemplo que hemos estado usando es algo contrived, por lo que ahora vamos a pasar a un ejemplo real de COM en acción: mostrar el cuadro de diálogo Abrir para que el usuario seleccione un archivo.

Siguientes

Ejemplo: El cuadro de diálogo Abrir