无法使用 ComPtr 创建我的 COM 类的实例

Cannot create an instance of my COM class with ComPtr

提问人:IRP_HANDLER 提问时间:11/17/2023 最后编辑:Remy LebeauIRP_HANDLER 更新时间:11/18/2023 访问量:72

问:

我在创建 COM 接口时遇到问题。

我将其定义如下:

struct __declspec( uuid( "36244c2e-4883-47cb-9e02-5d4ea3cc38d9" ) )
IMyObject : IPersist, IPropertyBag
{
    virtual void __stdcall DoObjectStuff() = 0;
};

HRESULT __stdcall CreateObject( IMyObject** myObject);

以及不完整的实现:

struct MyObject : IMyObject
{
    // reference counter
    long m_count;

    MyObject()
        :
        m_count( 0 )
    {
        printf("Creating MyObject!\n");
    }


    // IUnknownInterface
    virtual ULONG __stdcall AddRef() override
    {
        // ...
    }

    virtual ULONG  __stdcall Release() override
    {
        // ...
    }

    virtual HRESULT __stdcall QueryInterface( REFIID riid, void** ppvObject )
    {
            ASSERT( ppvObject );

            const auto id = riid;

          if( id == __uuidof( IMyObject ) ||
              id == __uuidof( IUnknown ) ) 
          {
             *ppvObject = static_cast<IMyObject*>( this );
          }
          else if( id == __uuidof( IPropertyBag ) )
          {
            *ppvObject = static_cast<IPropertyBag*>( this );
          }
          else if( id == __uuidof( IPersist ))
          {
                *ppvObject = static_cast<IPersist*>( this );
          }
          else
          {
                // unsupported interface
                 *ppvObject = nullptr;
                 return E_NOINTERFACE;
          }

         static_cast<IUnknown*>( *ppvObject )->AddRef();
         return S_OK;
    }




    // IPersist
    virtual HRESULT __stdcall GetClassID(CLSID* pClassID) override
    {
        // ...
    }

    // IPropertyBag
    virtual HRESULT __stdcall Read( LPCOLESTR pszPropName, VARIANT* pVar, IErrorLog* pErrorLog ) override
    {
        // ...
    }

    virtual HRESULT __stdcall Write( LPCOLESTR pszPropName, VARIANT* pVar ) override
    {
           // ...
    }

    // IMyObject
    virtual void __stdcall DoObjectStuff() override
    {
        std::cout << "Object stuff is being done!" << std::endl;
    }

};

HRESULT __stdcall CreateObject( IMyObject** myObject )
{
    // creates the object
}

现在,IPropertyBagIPersist 都实现了 IUnknown,我是否还需要从中显式派生我的接口?IUnknown

我在这里面临的问题是,当我尝试创建一个对象时:

using namespace Microsoft::WRL;
ComPtr<IMyObject> myObject;

我收到错误 C2385,这是怎么回事?

它说问题出在里面的函数上。Release()ComPtr

C++ Windows WinAPI 接口 COM

评论

1赞 RbMm 11/17/2023
我是否还需要从 IUnknown 显式派生我的接口?-不。您可以使用或添加到声明ComPtr<MyObject>virtual ULONG __stdcall Release();IMyObject
6赞 Igor Tandetnik 11/17/2023
IMyObject : IPersist, IPropertyBag这是行不通的。COM 对象可能派生自多个接口;但对于 COM 接口,不支持多重继承。 最终派生自 twice;这将导致问题。最有可能的是,您希望从 ,然后从所有三个 和 派生IMyObjectIUnknownIMyObjectIUnknownMyObjectIMyObjectIPersistIPropertyBag
2赞 Igor Tandetnik 11/17/2023
每个接口指针都必须明确地转换为 。因此不可转换。IUnknown*IMyObject*
1赞 Igor Tandetnik 11/17/2023
不相关,您的实现是错误的。它声称你的对象不支持,这当然是必须的。QueryInterfaceIUnknown
1赞 IInspectable 11/17/2023
“IPersist 的 Release 实现将指向与 Release 的 IPropertyBag 实现相同的地址” - 您可以以这种方式实现它,但不要求地址相同。COM 引用计数严格按接口进行。COM 中的派生相当于接口重用,它可能作为代码重用实现,也可能不实现。

答:

1赞 Jeaninez - MSFT #1

根据 IgorTandetnik 的建议:

仅限于继承,然后在创建对象时继承自所有这些对象 (, , )。IMyObjectIUnknownIMyObjectIPersistIPortable