1

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

现在我看到对象 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

我不知道我是如何指出QueryInterface应该通过 OLE 和 RPC 调用的。有任何想法吗?

4

2 回答 2

1

该类的线程模型B是“免费的”,而我正在从多线程上下文创建对象。切换B到“两者”解决了这个问题。

于 2011-05-16T10:42:33.733 回答
1

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

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

然后您将其更改FreeCOM 认为合适”Both意思,正式允许 COM 将对象放入与调用者相同的单元中,并且不需要编组,因此您不会再看到那个看起来很奇怪的错误代码。ApartmentFree

于 2011-05-16T11:40:46.217 回答