本記事は、COM Advent Calendar 2014 – Qiitaの17日目の記事です。
前回のマーシャリングできないインタフェースの話に続いて、今回はオブジェクト自らがマーシャリングの禁止を宣言する話です。
マーシャリングできないことを表明するインタフェースINoMarshalがWindows 8で追加されました。早速サンプルコードを出します。
#include <iostream> #include <thread> #include <windows.h> #include <shlwapi.h> #include <atlbase.h> #include <atlcom.h> #include <atlutil.h> class ATL_NO_VTABLE Hoge : public ATL::CComObjectRootEx<ATL::CComSingleThreadModel> , public ATL::CComCoClass<Hoge> , public ISequentialStream { public: BEGIN_COM_MAP(Hoge) COM_INTERFACE_ENTRY(ISequentialStream) COM_INTERFACE_ENTRY_IID(__uuidof (INoMarshal), ISequentialStream) END_COM_MAP() IFACEMETHOD(Read)( _Out_writes_bytes_to_(cb, *pcbRead) void* pv, _In_ ULONG cb, _Out_opt_ ULONG *pcbRead) override { if (pcbRead == nullptr) return E_POINTER; *pcbRead = 0; return S_OK; } IFACEMETHOD(Write)( _In_reads_bytes_(cb) const void* pv, _In_ ULONG cb, _Out_opt_ ULONG *pcbWritten) override { return E_NOTIMPL; } }; int main() { std::cout << std::hex << std::showbase; if (FAILED(CoInitializeEx(nullptr, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE))) { return 1; } { ATL::CComObjectStackEx<Hoge> hoge; IStream* s; std::cout << CoMarshalInterThreadInterfaceInStream( IID_IUnknown, &hoge, &s) << std::endl; } CoUninitialize(); } |
実行結果はこうでした。
0x80004021
CoMarshalInterThreadInterfaceInStreamで指定しているのは本来マーシャリングできるIUnknownにもかかわらず、このようにエラーコード0x80004021 (CO_E_NOT_SUPPORTED)になりました。
余談です。INoMarshalはメソッドを全く持たないため、C++クラスHogeの基底クラスに入れずに実装しました。COM_INTERFACE_ENTRY_IIDを使っています。
COM_INTERFACE_ENTRY_IID(__uuidof (INoMarshal), ISequentialStream) |
こうすると、QueryInterfaceで__uuidof (INoMarshal)が来たとき、static_cast<ISequentialStream*>(this)相当を返すという意味合いになります。INoMarshalはIUnknownと全く同じ構造のvtblになるため、ISequentialStreamに限らずIUnknownから派生する任意のインタフェースを指定して構いません。
なお、INoMarshalはおそらくWinRT API (Windows Runtime)用に追加されたものですが、このようにWinRT APIと無関係に使用できます。
スポンサード リンク |
この記事のカテゴリ
- COM ⇒ マーシャル禁止のオブジェクト