为什么QueryInterface()会失败,当接口确实在Windows中实现并具有内置编组器时
Why would QueryInterface() fail when the interface is surely implemented and has built-in marshaller in Windows?
我有以下设置。有一个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()
, CC_8隐式地上传到IUnknown*
,后者传递给COM编组器。被封送的IUnknown*
到达另一个进程的服务器,在那里获得IUnknown*
,然后有一个QueryInterface()
调用从同一个对象封送IStream*
, QueryInterface()
失败。
这看起来很疯狂,因为编组IStream*
应该在任何时候都能工作——Windows中已经预先安装了这个接口的编组器。
为什么它不可能工作,我如何找到原因?
符合该行为的一种可能情况如下:
- 在调用者和被调用者之间没有任何封送
- 接口指针是有效的
- 然而,实现
IStream
的对象没有相应的COM_INTERFACE_ENTRY
映射条目,也没有使接口可用,调用者可能通过非com方式获得指针,例如直接c++强制转换
这很容易通过在调用之前在调用方端检查流来检查。
在这种情况下,被调用者可以将reinterpret_cast
转换为IStream
,并使其正常工作。
您可以让IDL导入objidl。或者在您自己的idl中手动定义IStream(及其祖先)(只是要确保使用标准的IID值)。然后你可以使用IStream而不是IUnknown作为你的参数类型,不用再担心QueryInterface()
了。
你可以用IDispatch代替IUnknown作为你的方法的参数类型。在我看来,服务器实际上有一个存根而不是流本身,因为它在另一个进程中。
这只是一个猜测
希望对大家有所帮助
- 内置函数可查看CPP中的成员变量
- 是否有内置方法可以强制转换为不同的基础类型,但保留常量限定符?
- 按字母顺序对字符串中的字母进行排序,而无需使用内置的 sort()
- 将字符串转换为浮点数或整数,而无需使用内置函数(如 atoi 或 atof)
- 如何从 c++ 中类中内置的数组继承
- 如何捕获 C++ 内置异常对象
- macOS 是内置在 clang 编译器中还是内置于 xcode ide 中?
- 将编译器开关添加到 Eclipse CDT 内置编译器设置生成?
- gcc Atomic在gcc 4.1.1中内置了奇怪的行为
- 是否有用于元素部分移位的 simd 指令/内在/内置指令?
- 何时包含内置类型和运算符的标头?
- 基本类型与内置类型有什么区别C++
- 是否可以在不依赖内置编译器的情况下拥有is_trivially_constructible的库实现
- glibc函数的GCC、-flto、-fno内置和自定义函数实现
- 替换C 中内置类型的交换实现
- 如何获取/实现类的内置类型成员变量"Uninitialized uses warning"消息?
- 为什么QueryInterface()会失败,当接口确实在Windows中实现并具有内置编组器时
- 实现TCP应用程序内置shell的简单方法
- 获取Firefox内置组件的接口实现
- 在 C++11 中,如何实现适合内置类型层次结构的算术类型