COM Kitaplığı

COM kullanan tüm işlemlerin COM kitaplığını başlatması ve sonlandırması gerekir. COM, özellik olmanın yanı sıra bu kütüphanede bazı önemli hizmetleri de uygular. Microsoft Windows'ta DLL'ler ve EXE'ler kümesi (öncelikli olarak Ole32.dll ve Rpcss.exe) olarak sağlanan COM kitaplığı aşağıdakileri içerir:

  • hem istemci hem de sunucu olmak üzere COM uygulamalarının oluşturulmasını kolaylaştıran az sayıda temel işlev. İstemciler için COM, nesne oluşturmaya yönelik temel işlevler sağlar. Sunucular için COM, nesnelerini açığa çıkarmanın araçlarını sağlar.

  • COM'un benzersiz bir sınıf tanımlayıcısından (CLSID) hangi sunucunun bu sınıfı uyguladığını ve bu sunucunun nerede bulunduğunu belirlediği uygulama bulucu hizmetleri. Bu hizmet, istemcilerin gelecekte değişebilecek olan paketlemeden bağımsız olabilmesi için nesne sınıfının kimliği ile uygulamanın paketlenmesi arasında, genellikle sistem kayıt defteri ile sağlanan, bir ara katman desteği içerir.

  • Yerel veya uzak bir sunucuda bir nesne çalışırken, saydam uzak yordam çağrıları yapılır.

  • Bir uygulamanın işlemi içinde belleğin nasıl tahsis edildiğini kontrol etmesine olanak sağlayan standart bir mekanizma, özellikle işbirliği yapan nesneler arasında aktarılması ve düzgün bir şekilde boşaltılması gereken bellekler için kullanılabilir.

Temel COM hizmetlerini kullanmak için, istemcilerde ve işlem dışı sunuculardaki tüm COM yürütme iş parçacıklarının, bellek ayırma çağrıları dışında başka bir COM işlevini çağırmadan önce CoInitialize veya CoInitializeEx işlevlerinden birini çağırması gerekir. CoInitializeEx diğer işlevin yerini alarak, iş parçacığının modelini belirtmenize olanak tanıyan bir parametre ekler: apartman iş parçacıklı veya serbest iş parçacıklı. CoInitialize çağrısı, iş parçacığı modelini daire iş parçacığı olarak ayarlar.

OLE bileşik belge uygulamaları, CoInitializeEx çağıran ve bileşik belgeler için gerekli bazı başlatmaları yapan OleInitialize işlevini çağırır. Bu nedenle, OleInitialize çağıran iş parçacıkları serbest iş parçacıklı olamaz. İstemciler ve sunuculardaki iş parçacıkları hakkında bilgi için bkz. İşlemler, İş Parçacıkları ve Konaklamalar.

İşlem içi sunucular başlatma işlevlerini çağırmaz çünkü zaten bunu yapmış bir işleme yüklenirler. Sonuç olarak, işlem içi sunucuların iş parçacığı modelini InprocServer32 anahtarı altında kayıt defterinde ayarlaması gerekir. İşlem içi sunuculardaki iş parçacığı oluşturma sorunları hakkında ayrıntılı bilgi için bkz. In-Process Sunucu İş Parçacığı Oluşturma Sorunları.

Kitaplığın başlatılmasını geri almak da önemlidir. Her çağrı için CoInitializeveya CoInitializeEx, karşılık gelen bir çağrı CoUninitializeolmalıdır. OleInitializeher çağrı için, OleUninitializeiçin karşılık gelen bir çağrı olmalıdır.

İşlem içi sunucular, yüklendikleri işlemin bu adımları zaten gerçekleştirdiğini varsayabilir.

Important

COM kullanan her iş parçacığı, diğer COM işlevlerini çağırmadan önce CoInitializeEx çağırmalıdır. Bu, en yaygın COM başlatma hatasıdır: başlatılmamış bir iş parçacığında CoCreateInstance veya diğer COM API'lerini çağırmak, CO_E_NOTINITIALIZED (0x800401F0) hatasıyla başarısız olur.

Tip

Önerilen desen — başlatmanın geri alınmasını sağlamak için bir RAII koruması kullanın:

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

wil kullanılamıyorsa, CoUninitialize() öğesini manuel olarak çağırın — her başarılı CoInitializeEx çağrısı tam olarak bir CoUninitialize çağrısıyla eşlenmelidir:

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

// ... use COM ...

CoUninitialize();

Important

Yaygın hatalar:

  • Geçerli iş parçacığında COM başlatmadan COM işlevlerini çağırma.
  • Uyumsuz CoInitializeEx / CoUninitialize çağrıları (başarılı olan her init tam olarak bir uninit gerektirir).
  • Aynı iş parçacığında daire modellerini karıştırma (önceki başarılı çağrı CoInitializeEx döndürdüğünden RPC_E_CHANGED_MODEfarklı bir modelle çağırma).

Bileşen Nesne Modeli