COM如何选择如何编组接口?

sha*_*oth 6 windows com interop com-interop

我得到它有三种方法在COM中实现编组:

  • typelib编组
  • 代理/存根编组
  • 通过对象实现IMarshal

现在组件消费者(用户)如何选择使用哪一个?它是自己决定并使用首选方式还是调用一些内置函数并解决了它的问题?

我目前遇到以下情况:我的组件实现了一个自定义接口ICustomInterface,该接口也是由另一家公司的组件实现的.我的组件没有typelib,也没有实现IMarshal.系统注册表包含HKCR\Interface {uuidof(ICustomInterface)}\ProxyStubClsid32密钥,其中包含代理/存根的GUID,可以跟踪到该其他公司提供的库.

现在,当我的组件使用者初始化我的组件时,它调用QueryInterface()从我的组件请求IMarshal,当返回E_NOINTERFACE时,它什么都不做.为什么这样 - 为什么不从其他公司的代理/存根库启动?

小智 5

如果通过在其{00020424-0000-0000-C000-000000000046}下添加CLSID HKCR\Interfaces\{iid}\ProxyStubClsid(其中{iid}是您的接口的GUID)将接口标记为使用标准封送程序,则COM运行时将使用typelib(oleautomation)编组.您还需要注册一个类型库,以便运行时提取参数信息,并且您只能使用某个类型的子集.这里这里还有一些(旧的)信息.

如果要使用由IDL的MIDL编译器生成的自定义代理/存根,则需要将接口注册表项更改为该代理对象的CLSID.这使您可以使用更广泛的类型,例如"原始"数组.

如果你支持IMarshal那么就会优先使用这些机制.这意味着您可以更改对象以聚合自由线程编组程序(使用其实现IMarshal),而无需更改注册表中的任何内容.这将避免创建任何代理.

希望这可以帮助.


And*_*ith 0

我对此有点生疏,但是你的项目中有一个名为blindquery的函数吗?(如果您创建了 C++ ATL 项目,则通常由向导声明)。函数内的断点。由于代码错误,由向导生成的函数经常会出现 queryinterface 返回 E_NOINTERFACE 的问题。

\n\n

从我的旧项目_blindquery 编辑(找到示例代码)

\n\n
class ATL_NO_VTABLE CChildEvents :\n    public CComObjectRootEx <CComSingleThreadModel>,\n    public CComCoClass<CChildEvents, &CLSID_ChildEvents>,\n    public IDispatchImpl<IChildEvents, &IID_IChildEvents, &LIBID_XXX>\n{\npublic:\n    CChildEvents(void) :\n    m_pItfMgr(0)\n    {\n    }\n\n    /* called from internalQI to tear off a new blind interface */\n    static HRESULT WINAPI   _BlindQuery(void *pvThis, REFIID riid, void **ppv, DWORD dw);\n\n    DECLARE_REGISTRY_RESOURCEID(IDR_CHILDEVENTS)\n    DECLARE_PROTECT_FINAL_CONSTRUCT()\n\n    BEGIN_COM_MAP(CChildEvents)\n        COM_INTERFACE_ENTRY(IChildEvents)\n        COM_INTERFACE_ENTRY(IDispatch)\n        COM_INTERFACE_ENTRY_FUNC_BLIND(0, _BlindQuery)\n    END_COM_MAP()\n};\n\n\nHRESULT WINAPI CChildEvents::_BlindQuery(void *pvThis, REFIID riid, void **ppv, DWORD /* dw */ )\n{\n    HRESULT hr = E_NOINTERFACE;\n    USES_CONVERSION;\n\n    try\n    {\n        if(pvThis == NULL)\n        {\n            ATLASSERT(FALSE);\n        }\n        else\n        {\n            /*\n            * cast the pvThis pointer to the actual class \xc2\xa3\n            * so we can use it here \xc2\xa3\n            * reinterpret_cast should be safe since we\'re calling ourself\n            */\n            CChildEvents    *pThis = reinterpret_cast < CChildEvents * > (pvThis);\n            if(pThis == NULL)\n            {\n                ATLASSERT(FALSE);\n            }\n            else\n            {\n\n                    /* check to see if it matches on of our children\'s DIID */\n                                    if(memcmp(&riid,&l_someotherguid,sizeof(GUID)) == 0) {\n\n                        /* if so cast to a IDispatch -- the standard for event interfaces */\n                        *ppv = reinterpret_cast < IDispatch * > (pvThis);\n\n                        /* addref */\n                        pThis->AddRef();\n\n                        /* reply */\n                        hr = S_OK;\n\n                }\n            }\n        }\n    }\n    catch(...)\n    {\n        ATLASSERT(FALSE);\n    }\n\n    /* must not be in our map - tell them to GO FISH */\n    return(hr);\n}\n
Run Code Online (Sandbox Code Playgroud)\n