Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Depois que um thread inicializa a biblioteca COM, é seguro para o thread usar interfaces COM. Para usar uma interface COM, o programa primeiro cria uma instância de um objeto que implementa essa interface.
Em geral, há duas maneiras de criar um objeto COM:
- O módulo que implementa o objeto pode fornecer uma função especificamente projetada para criar instâncias desse objeto.
- Como alternativa, COM fornece uma função de criação genérica chamada CoCreateInstance.
Por exemplo, pegue o objeto Shape hipotético do tópico O que é uma interface COM?. Nesse exemplo, o objeto Shape implementa uma interface chamada IDrawable. A biblioteca de gráficos que implementa o objeto Shape pode exportar uma função com a seguinte assinatura.
// Not an actual Windows function.
HRESULT CreateShape(IDrawable** ppShape);
Dada essa função, você pode criar um novo objeto Shape da seguinte maneira.
IDrawable *pShape;
HRESULT hr = CreateShape(&pShape);
if (SUCCEEDED(hr))
{
// Use the Shape object.
}
else
{
// An error occurred.
}
O parâmetro ppShape é do tipo pointer-to-pointer-to-IDrawable. Se você não viu esse padrão antes, a dupla indireção pode ser intrigante.
Considere os requisitos da função CreateShape. A função deve retornar um ponteiro IDrawable ao chamador. Mas o valor de retorno da função já é usado para o código de erro/sucesso. Portanto, o ponteiro deve ser retornado através de um argumento para a função. O chamador passará uma variável do tipo IDrawable* para a função e a função substituirá essa variável por um novo ponteiro IDrawable. Em C++, há apenas duas maneiras de uma função substituir um valor de parâmetro: passar por referência ou passar por endereço. A COM utiliza esta última, "pass-by-address". E o endereço de um ponteiro é um ponteiro para um ponteiro, portanto, o tipo de parâmetro deve ser IDrawable**.
Aqui está um diagrama para ajudar a visualizar o que está acontecendo.
A função CreateShape usa o endereço de pShape (&pShape) para escrever um novo valor de ponteiro para pShape.
CoCreateInstance: Uma maneira genérica de criar objetos
A funçãoCoCreateInstance fornece um mecanismo genérico para criar objetos. Para entender CoCreateInstance, lembre-se de que dois objetos COM podem implementar a mesma interface e um objeto pode implementar duas ou mais interfaces. Assim, uma função genérica que cria objetos precisa de duas informações.
- Qual o objeto a criar?
- Que interface se deve obter do objeto?
Mas como indicar essa informação quando chamamos a função? Em COM, um objeto ou uma interface é identificado atribuindo-lhe um número de 128 bits, chamado de identificador global exclusivo (GUID). Os GUIDs são gerados de uma forma que os torna efetivamente únicos. GUIDs são uma solução para o problema de como criar identificadores exclusivos sem uma autoridade de registro central. Os GUIDs às vezes são chamados de identificadores universalmente exclusivos (UUIDs). Antes do COM, eles eram usados em DCE/RPC (Distributed Computing Environment/Remote Procedure Call). Existem vários algoritmos para criar novos GUIDs. Nem todos esses algoritmos garantem estritamente a exclusividade, mas a probabilidade de criar acidentalmente o mesmo valor GUID duas vezes é extremamente pequena — efetivamente zero. Os GUIDs podem ser usados para identificar qualquer tipo de entidade, não apenas objetos e interfaces. No entanto, esse é o único uso que nos preocupa neste módulo.
Por exemplo, a biblioteca Shapes pode declarar duas constantes GUID:
extern const GUID CLSID_Shape;
extern const GUID IID_IDrawable;
(Você pode supor que os valores numéricos reais de 128 bits para essas constantes sejam definidos em outro lugar.) A constante CLSID_Shape identifica o objeto Shape, enquanto a constante IID_IDrawable identifica a interface IDrawable. O prefixo "CLSID" significa identificador de classe, e o prefixo IID significa identificador de interface. Estas são convenções de nomenclatura padrão em COM.
Considerando esses valores, você criaria uma nova instância de Shape da seguinte maneira:
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.
}
A funçãoCoCreateInstance tem cinco parâmetros. O primeiro e o quarto parâmetros são o identificador de classe e o identificador de interface. Na verdade, esses parâmetros informam à função: "Criar o objeto Shape e me dar um ponteiro para a interface IDrawable."
Defina o segundo parâmetro como NULL. (Para obter mais informações sobre o significado desse parâmetro, consulte o tópico de agregação na documentação COM.) O terceiro parâmetro usa um conjunto de sinalizadores cujo objetivo principal é especificar o contexto de execução para o objeto. O contexto de execução especifica se o objeto é executado no mesmo processo que o aplicativo; num processo diferente no mesmo computador; ou num computador remoto. A tabela a seguir mostra os valores mais comuns para esse parâmetro.
| Bandeira | Descrição |
|---|---|
| CLSCTX_INPROC_SERVER | O mesmo processo. |
| CLSCTX_LOCAL_SERVER | Processo diferente, mesmo computador. |
| CLSCTX_REMOTE_SERVER | Computador diferente. |
| CLSCTX_ALL | Use a opção mais eficiente que o objeto suporta. (A classificação, do mais eficiente ao menos eficiente, é: em processo, fora de processo e entre computadores.) |
A documentação de um componente específico pode informar qual contexto de execução o objeto suporta. Caso contrário, utilize CLSCTX_ALL. Se você solicitar um contexto de execução que o objeto não suporta, a funçãoCoCreateInstanceretornará o código de erro REGDB_E_CLASSNOTREG. Esse código de erro também pode indicar que o CLSID não corresponde a nenhum componente registrado no computador do usuário.
O quinto parâmetro em CoCreateInstance recebe um ponteiro para a interface. Como CoCreateInstance é um mecanismo genérico, este parâmetro não pode ser tipado estritamente. Em vez disso, o tipo de dados é void**, e o chamador deve converter o endereço do ponteiro para um tipo void**. Esse é o objetivo do reinterpret_cast no exemplo anterior.
É crucial verificar o valor de retorno de CoCreateInstance. Se a função retornar um código de erro, o ponteiro da interface COM é inválido, e tentar desreferenciar ele pode fazer com que o programa falhe.
Internamente, a funçãoCoCreateInstance usa várias técnicas para criar um objeto. No caso mais simples, ele procura o identificador de classe no registro. A entrada do Registro aponta para uma DLL ou EXE que implementa o objeto. CoCreateInstance também pode utilizar informações de um catálogo COM+ ou de um manifesto SxS (lado a lado). Independentemente disso, os detalhes são transparentes para o chamador. Para obter mais informações sobre os detalhes internos do CoCreateInstance, consulte de clientes e servidores COM.
O exemplo Shapes que temos usado é um pouco inventado, então agora vamos passar para um exemplo do mundo real de COM em ação: exibir a caixa de diálogo Abrir para o usuário selecionar um arquivo.
Seguinte
Exemplo: A caixa de diálogo Abrir