COM如何select如何编组接口?

就我所知,有三种方法可以在COM中实现编组:

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

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

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

现在,当我的组件使用者初始化我的组件时,它会调用QueryInterface(),从我的组件中请求IMarshal,当返回E_NOINTERFACE时它什么也不做。 这是为什么 – 为什么不从其他公司的代理/存根库踢?

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

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

如果你支持IMarshal那么优先使用这些机制。 这意味着你可以改变你的对象来聚合自由线程封送IMarshal (使用它的IMarshal实现),而不必在注册表中改变任何东西。 这将避免创建任何代理。

希望这可以帮助。

我有点生疏,但是你的项目中是否有一个名为blindquery的函数? (如果你创建了一个C ++ ATL项目,它通常由向导声明)。 函数内部的断点。 该向导生成的函数通常在查询接口返回E_NOINTERFACE时由于错误的代码而出现问题。

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

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