不情愿地通过 RPC 调用 QueryInterface

Unwillingly calling QueryInterface via RPC

本文关键字:调用 QueryInterface RPC 不情愿      更新时间:2023-10-16

在我的应用程序中,我创建了一个对象 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。 有什么想法吗?

从你的描述来看,这绝对是编组开始了。编组是通过RPC隧道调用来完成的,所以它看起来很奇怪,但这就是在Windows上完成的方式。

消费者线程可能用COINIT_APARTMENTTHREADED调用CoInitializeEx()。由于要创建的对象被标记为Free因此不可能在调用方的公寓中创建(请参阅有关公寓的非常好的解释)。相反,COM 试图打开编组,您可能没有任何促进编组的东西,在这种情况下CoCreateInstance()返回E_NOINTERFACE因为 COM 内部工作请求一堆用于封送的接口,一旦所有这些请求失败,它最终会得到E_NOINTERFACE并返回它,这当然对您来说根本不方便。

然后你从Free更改为Both这意味着"Apartment COM 认为合适的Free"COM 被正式允许将对象放入与调用方相同的公寓中,并且不需要编组,因此您不再看到那个看起来很奇怪的错误代码。

B类的线程模型是"Free",而我正在从多线程上下文中创建对象。 将B切换到"两者"解决了这个问题。