不情愿地通过RPC调用QueryInterface

时间:2011-05-16 10:05:50

标签: c++ com rpc inproc

在我的应用程序中,我创建了一个对象A,它通过CreateInstance创建一个对象B.两个对象都应该存在于同一个进程中。

现在我看到对象B,当被问到某个接口时,正在返回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。有什么想法吗?

2 个答案:

答案 0 :(得分:1)

B类的线程模型是'Free',而我是从MultiThreaded上下文创建对象的。将B切换为“Both”解决了这个问题。

答案 1 :(得分:1)

从你的描述中它绝对是marshalling kicking in。编组通过RPC通过隧道调用完成,因此看起来很奇怪,但这就是在Windows上完成的。

消费者主题可能会使用CoInitializeEx()调用COINIT_APARTMENTTHREADED。由于要创建的对象标记为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正式被允许将对象放入与呼叫者相同的公寓中,并且不需要编组,因此您不要再看看那个奇怪的错误代码了。