Bibliothèque COM

Tout processus qui utilise COM doit initialiser et annuler l’initialisation de la bibliothèque COM. En plus d’être une spécification, COM implémente également certains services importants dans cette bibliothèque. Fourni sous la forme d’un ensemble de DLL et d’EXEs (principalement Ole32.dll et Rpcss.exe) dans Microsoft Windows, la bibliothèque COM inclut les éléments suivants :

  • Un petit nombre de fonctions fondamentales qui facilitent la création d’applications COM, à la fois client et serveur. Pour les clients, COM fournit des fonctions de base pour la création d’objets. Pour les serveurs, COM fournit les moyens d’exposer leurs objets.

  • Services de localisateur d’implémentation par le biais desquels COM détermine, à partir d’un identificateur de classe unique (CLSID), ce serveur implémente cette classe et l’emplacement où se trouve ce serveur. Ce service inclut la prise en charge d’un niveau d’indirection, généralement un registre système, entre l’identité d’une classe d’objet et l’empaquetage de l’implémentation afin que les clients soient indépendants de l’empaquetage, ce qui peut changer à l’avenir.

  • La procédure distante transparente appelle lorsqu’un objet est en cours d’exécution dans un serveur local ou distant.

  • Mécanisme standard permettant à une application de contrôler la façon dont la mémoire est allouée au sein de son processus, en particulier la mémoire qui doit être passée entre les objets de coopération afin qu’elle puisse être libérée correctement.

Pour utiliser les services COM de base, tous les threads COM d’exécution dans les clients et les serveurs hors processus doivent appeler la fonction CoInitialize ou CoInitializeEx avant d’appeler une autre fonction COM, à l’exception des appels d’allocation de mémoire. CoInitializeEx remplace l’autre fonction, en ajoutant un paramètre qui vous permet de spécifier le modèle de thread : thread cloisonné ou thread libre. Un appel à CoInitialize définit simplement le modèle de thread sur « thread cloisonné ».

Les applications de documents composés OLE appellent la fonction OleInitialize , qui appelle CoInitializeEx et effectue également une initialisation requise pour les documents composés. Par conséquent, les threads qui appellent OleInitialize ne peuvent pas être threads libres. Pour plus d’informations sur le threading dans les clients et les serveurs, consultez Processus, threads et cloisonnements.

Les serveurs in-process n’appellent pas les fonctions d’initialisation, car ils sont chargés dans un processus qui l’a déjà fait. Par conséquent, les serveurs in-process doivent définir leur modèle de thread dans le Registre sous la clé InprocServer32 . Pour plus d’informations sur les problèmes de multithreading des serveurs In-Process, consultez Problèmes de multithreading des serveurs In-Process.

Il est également important de désinitialiser la bibliothèque. Pour chaque appel à CoInitialize ou CoInitializeEx, il doit y avoir un appel correspondant à CoUninitialize. Pour chaque appel à OleInitialize, il doit y avoir un appel correspondant à OleUninitialize.

Les serveurs in-process peuvent supposer que le processus dans lequel ils sont chargés a déjà effectué ces étapes.

Important

Chaque thread qui utilise COM doit appeler CoInitializeEx avant d’appeler une autre fonction COM. Il s’agit de l’erreur d’initialisation COM la plus courante : l’appel CoCreateInstance ou d’autres API COM sur un thread qui n’a pas été initialisé échoue avec CO_E_NOTINITIALIZED (0x800401F0).

Tip

Modèle recommandé : utilisez un garde RAII pour garantir la non initialisation :

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

Si wil n’est pas disponible, appelez CoUninitialize() manuellement : chaque appel réussi CoInitializeEx doit être jumelé avec exactement un CoUninitialize appel :

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

// ... use COM ...

CoUninitialize();

Important

Erreurs courantes :

  • Appel de fonctions COM sans initialiser COM sur le thread actuel.
  • Appels CoInitializeEx / CoUninitialize non correspondants (chaque initialisation réussie nécessite exactement un seul appel à uninit).
  • Mélange de modèles d’appartement dans le même thread (l’appel à CoInitializeEx avec un modèle différent de celui d’un appel précédent réussi renvoie RPC_E_CHANGED_MODE).

Le Modèle Objet Composant (COM)