在我的应用程序中,我通过 CreateInstance
创建了一个对象 A,该对象又创建了一个对象 B。这两个对象应该存在于同一个进程中。
现在我看到对象 B 在请求某个接口(interface)时返回 E_NOINTERFACE,尽管我在 COM_MAP 中定义了它:
class B:
{
// ....
BEGIN_COM_MAP(B)
COM_INTERFACE_ENTRY(IB)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(IXXX) // the interface I'm interested in
END_COM_MAP()
// .....
};
A 代码:
#define FORWARD_ERROR( expr ) { hr=expr; if( !SUCCEEDED( hr ) ) return hr;}
IBPtr b;
FORWARD_ERROR( b.CreateInstance( __uuidof( B ), 0, CLSCTX_INPROC_SERVER ) );
IXXXPtr x;
HRESULT hrIf = b.QueryInterface( __uuidof( IXXX ), x );
// ===> now x is NULL, and hrIf contains E_NOINTERFACE
当我调试它并在 COM_MAP 中放置一个断点时,我没有在最低帧中看到我的源代码,而是一些 ole32.dll 的 CRpcThread::WorkerLoop
。
我不知道我是如何指示应该通过 OLE 和 RPC 调用 QueryInterface
的。有什么想法吗?
最佳答案
根据你的描述肯定是marshalling kicking in .编码是通过 RPC 隧道调用完成的,因此它看起来很奇怪,但这就是它在 Windows 上完成的方式。
消费者线程可能使用 COINIT_APARTMENTTHREADED
调用了 CoInitializeEx()
。由于要创建的对象被标记为 Free
,因此它不可能在调用者的公寓中创建(参见 this very good explanation on apartments )。相反,COM 试图打开编码,而您可能没有 anything to facilitate marshalling在这种情况下 CoCreateInstance()
返回 E_NOINTERFACE
因为 COM 内部工作请求 a bunch of interfaces it would use for marshalling一旦所有这些请求都失败,它就会以 E_NOINTERFACE
结束并返回它,这当然对您来说一点都不方便。
然后你从 Free
更改为 Both
这意味着 "Apartment
of Free
as COM sees fit" COM 被正式允许将对象放入与调用者相同的单元中,并且不需要编码,因此您不会再看到那个看起来很奇怪的错误代码。
关于c++ - 不情愿地通过 RPC 调用 QueryInterface,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6015789/