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

现在,尽管我在COM_MAP中定义了对象B,但当我要求对象B提供某个接口(interface)时,它返回E_NOINTERFACE:

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上完成的方式。

使用者线程可能使用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正式被允许将对象与调用者放到同一套公寓中,而无需进行编码,因此您不再看到看起来很奇怪的错误代码。

关于c++ - 不愿意通过RPC调用QueryInterface,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6015789/

10-11 23:15
查看更多