前回のCreateDispTypeInfoとCreateStdDispatchを使ってみるを書いた後、ATL::IDispatchImplとの組み合わせでも作れるのではないかと思い、やってみることにしました。

#define _ATL_NO_AUTOMATIC_NAMESPACE
 
#include <iostream>
#include <windows.h>
#include <atlbase.h>
#include <atlcom.h>
#include <atlutil.h>
 
class Module : public ATL::CAtlExeModuleT<Module> {};
Module module;
 
// ダミー
// {34F91FCB-7237-4EA7-B5E5-3FB7FDDD87AC}
static constexpr CLSID CLSID_Hoge = { 0x34f91fcb, 0x7237, 0x4ea7, { 0xb5, 0xe5, 0x3f, 0xb7, 0xfd, 0xdd, 0x87, 0xac } };
 
interface DECLSPEC_UUID("6ae160da-9e37-4f46-83bd-bf166a82f871") IFunc2
  : IDispatch
{
  virtual void STDMETHODCALLTYPE Func() = 0;
};
 
class ATL_NO_VTABLE Hoge
  : public ATL::CComObjectRootEx<ATL::CComMultiThreadModel>
  , public ATL::CComCoClass<Hoge>
  , public ATL::IDispatchImpl<IFunc2, &__uuidof(IFunc2)>
{
public:
  BEGIN_COM_MAP(Hoge)
    COM_INTERFACE_ENTRY(IFunc2)
    COM_INTERFACE_ENTRY(IDispatch)
  END_COM_MAP()
 
  DECLARE_NO_REGISTRY()
 
  static void WINAPI ObjectMain(bool starting)
  {
    if (!starting)
    {
      _tihclass::Cleanup(reinterpret_cast<DWORD_PTR>(&_tih));
    }
  }
 
  HRESULT FinalConstruct()
  {
    return InitializeTypeInfo();
  }
 
  void STDMETHODCALLTYPE Func() override
  {
    std::cout << "Hoge::Invoke" << std::endl;
  }
 
  DECLARE_NOT_AGGREGATABLE(Hoge)
 
private:
  static HRESULT InitializeTypeInfo()
  {
    auto& ti = _tih.m_pInfo;
    if (ti != nullptr)
    {
      return S_OK;
    }
    static METHODDATA md[]
    {
      {
        const_cast<OLECHAR*>(L"Func"),
        nullptr,
        DISPID_VALUE,
        7, // 0~2はIUnknownの各メソッド、3~6はIDispatchの各メソッドのため。
        CC_STDCALL,
        0,
        DISPATCH_METHOD,
        VT_EMPTY
      },
    };
    static INTERFACEDATA id
    {
      md, ARRAYSIZE(md),
    };
    return CreateDispTypeInfo(&id, LOCALE_SYSTEM_DEFAULT, &ti);
  }
};
 
OBJECT_ENTRY_NON_CREATEABLE_EX_AUTO(CLSID_Hoge, Hoge)
 
int main()
{
  try
  {
    ATLENSURE_SUCCEEDED(CoInitializeEx(
      nullptr, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE));
 
    ATL::CComPtr<IDispatch> hoge;
    ATLENSURE_SUCCEEDED(Hoge::CreateInstance(&hoge));
 
    hoge.Invoke0(static_cast<DISPID>(DISPID_VALUE));
  }
  catch (const ATL::CAtlException& e)
  {
    std::clog << std::hex << std::showbase;
    std::clog << e.m_hr << ' ';
    std::clog << ATL::AtlGetErrorDescription(e) << std::endl;
  }
 
  CoUninitialize();
}

コード中に現れるtihclass_tihは、ATL::IDispatchImplのprotectedメンバーです。

後始末をObjectMain関数でやることにしたため、OBJECT_ENTRY_NON_CREATEABLE_EX_AUTOを使用しています。

実験としてやってみたことです。実用性は考えていません。特段、コード量が減るわけでもないので、私は前回の方法でいいやと思いました。

スポンサード リンク

この記事のカテゴリ

  • ⇒ CreateDispTypeInfoとATL::IDispatchImplを使ってみる
  • ⇒ CreateDispTypeInfoとATL::IDispatchImplを使ってみる