ATLを使ってCOMオブジェクトを作る最小コードの例です。1アプリケーションの中でCOMオブジェクトの作成が必要になったという想定です。すなわち、この例にクラスファクトリやOBJECT_ENTRY_AUTOは登場しません。

#define _ATL_NO_AUTOMATIC_NAMESPACE
 
#include <iostream>
#include <atlbase.h>
#include <atlcom.h>
 
MIDL_INTERFACE("0f9a78ce-4f58-4160-9889-e3bd4485c92d") ITest : IUnknown
{
  virtual HRESULT STDMETHODCALLTYPE Test() = 0;
};
 
class ATL_NO_VTABLE TestImpl
  : public ATL::CComObjectRootEx<ATL::CComMultiThreadModel>
  , public ITest
{
  DECLARE_NOT_AGGREGATABLE(TestImpl)
 
  BEGIN_COM_MAP(TestImpl)
    COM_INTERFACE_ENTRY(ITest)
  END_COM_MAP()
 
public:
  HRESULT FinalConstruct() throw()
  {
    std::cout << "TestImpl::FinalConstruct" << std::endl;
    return S_OK;
  }
 
  HRESULT FinalRelease() throw()
  {
    std::cout << "TestImpl::FinalRelease" << std::endl;
    return S_OK;
  }
 
  virtual HRESULT STDMETHODCALLTYPE Test() throw() override
  {
    std::cout << "TestImpl::Test" << std::endl;
    return S_OK;
  }
 
  void Test2()
  {
    std::cout << "TestImpl::Test2 (non-virtual)" << std::endl;
  }
};
 
class Module : public ATL::CAtlExeModuleT<Module> {};
Module module;
 
int main()
{
  try
  {
    ATL::CComObject<TestImpl>* impl = nullptr;
    auto hr = ATL::CComObject<TestImpl>::CreateInstance(&impl);
    ATLENSURE_SUCCEEDED(hr);
    ATL::CComPtr<ITest> test(impl); // ここでAddRefが呼ばれる
    impl->Test2();
 
    test->Test();
  }
  catch (const ATL::CAtlException& e)
  {
    std::cerr << std::hex << std::showbase << "Failed: " << e << std::endl;
  }
}

この例では、オブジェクトの作成にATL::CComObject<>::CreateInstanceを使っています。これは、ATLのオブジェクト作成の関数において、実装クラスへのポインタを返す唯一の存在です(これ以外はみんなインタフェースへのポインタを返します)。そのことを示す意図を込めて、上記コードでも、どのインタフェースのメソッドでもないTest2メンバ関数を呼び出しています。

ただし、ATL::CComObject<>::CreateInstanceには注意点があります。それは、この関数から返った直後のオブジェクトは原則として参照カウントが0ということです。上のコードのように、すぐにAddRef(あるいはQueryInterface)を呼びましょう。


スポンサード リンク

この記事のカテゴリ

  • ⇒ ATLでCOMインタフェースを実装するコード例
  • ⇒ ATLでCOMインタフェースを実装するコード例
  • ⇒ ATLでCOMインタフェースを実装するコード例