为什么QueryInterface()会失败,当接口确实实现并在Windows中有内置编组器? [英] Why would QueryInterface() fail when the interface is surely implemented and has built-in marshaller in Windows?
问题描述
我有以下设置。有一个COM服务器安装到COM +(在单独的进程中运行),并具有此接口定义:
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; //控制权通过此处
}
//无论
}
$ c $因此我有 IStream *
传入 callComObject() / code>在客户端被隐式转换为 IUnknown *
,后者被传递给COM编组器。编组 IUnknown *
在另一个进程中到达服务器,并且获得 IUnknown *
,然后有 QueryInterface()
从同一对象调用marshall IStream *
,并且 QueryInterface()
失败。
这看起来很疯狂,因为编组 IStream *
应该在任何时候都工作 - 有一个marshaller
为什么可能无法正常工作,如何找到原因?
解决方案符合行为的一种可能情况如下:
- 在调用者和被调用者之间没有任何区别
- 接口指针有效
- 但是实现
IStream ,没有相应的 COM_INTERFACE_ENTRY
映射条目,并且不使接口可用,调用者可能已通过非COM方式获取指针,例如直接C ++转换
这很容易通过 QueryInterface
在呼叫前的呼叫方。
此方案中的被调用者只需 reinterpret_cast
到 IStream
并且它很好地工作。
I have the following setup. There's a COM server that is installed into COM+ (to run in a separate process) and has this interface definition:
[object, uuid("InterfaceIdHere"), nonextensible, oleautomation, hidden]
interface IMyInterface : IUnknown {
HRESULT MyMethod( [in] IUnknown* param );
};
The caller calls it like this:
HRESULT callComObject(IStream* stream)
{
return comObject->MyMethod(stream);
}
Note that here IStream*
is implicitly upcasted to IUnknown*
. This is done because declaring a parameter of type IStream*
in IDL caused some problems that I can't recall right now. Anyway it's always a valid IStream*
that is passed in place of IUnknown*
.
The COM server side has this implementation of 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
}
So I have IStream*
passed into callComObject()
on the client side which is implicitly upcasted to IUnknown*
and the latter is passed to the COM marshaller. The marshalled IUnknown*
reaches the server in another process and there IUnknown*
is obtained and then there's a QueryInterface()
call to marshall IStream*
from the same object and that QueryInterface()
fails.
This looks insane, because marshalling IStream*
should just work at all times - there's a marshaller for this interface pre-installed in Windows.
Why could it possible not work and how do I find the reason?
解决方案 One of the possible scenarios that matches the behavior is the following:
- you don't have any marhshaling between caller and callee
- the interface pointer is valid
- however the object which implements
IStream
, does not have a corresponding COM_INTERFACE_ENTRY
map entry and does not make the interface available, the caller might have obtained the pointer via non-COM way, e.g. direct C++ cast
This is easy to check by QueryInterface
'ing the stream on the caller side before the call.
The callee in this scenario can just reinterpret_cast
to IStream
and have it nicely working.
这篇关于为什么QueryInterface()会失败,当接口确实实现并在Windows中有内置编组器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!