我有以下设置。 COM +中安装了一个COM服务器(在单独的进程中运行)并具有此接口定义:
[object, uuid("InterfaceIdHere"), nonextensible, oleautomation, hidden]
interface IMyInterface : IUnknown {
HRESULT MyMethod( [in] IUnknown* param );
};
来电者称之为:
HRESULT callComObject(IStream* stream)
{
return comObject->MyMethod(stream);
}
请注意,此处IStream*
会隐式上传至IUnknown*
。这样做是因为在IDL中声明类型为IStream*
的参数会导致一些我现在无法回想起的问题。无论如何,它总是有效IStream*
代替IUnknown*
。
COM服务器端具有MyMethod()
的实现:
STDMETHODIMP CServer::MyMethod(IUnknown* param)
{
if(param == 0) {
return E_INVALIDARG;
}
ATL::CComQIPtr<IStream> stream(param);
if(stream == 0) {
return E_INVALIDARG;// control passes HERE
}
// whatever
}
所以我在客户端传递了IStream*
callComObject()
,它被隐含地提升到IUnknown*
,后者被传递给COM编组。已编组的IUnknown*
在另一个进程中到达服务器并获得IUnknown*
,然后QueryInterface()
来自同一对象的IStream*
QueryInterface()
调用IStream*
失败。
这看起来很疯狂,因为编组{{1}}应该始终有效 - 在Windows中预装了此接口的编组器。
为什么它可能无法工作,我如何找到原因?
答案 0 :(得分:4)
与行为匹配的可能方案之一如下:
IStream
的对象没有相应的COM_INTERFACE_ENTRY
映射条目并且不使接口可用,调用者可能已经通过非COM方式获得指针,例如,直接C ++演员通过QueryInterface
在呼叫之前调用呼叫方的流很容易检查。
此方案中的被调用方可以reinterpret_cast
到IStream
并且可以很好地工作。
答案 1 :(得分:2)
您可以将IDL导入objidl.idl,或者在您自己的IDL中手动定义IStream(和祖先)(只需确保使用标准IID值)。然后,您可以使用IStream而不是IUnknown作为参数类型,而不再担心QueryInterface()
。
答案 2 :(得分:1)
您可以将IDispatch替换为IUnknown作为方法的参数类型。在我看来,服务器实际上有一个存根而不是流本身,因为它在另一个进程中。
这只是猜测
我希望这会有所帮助