【问题标题】:Unwillingly calling QueryInterface via RPC不情愿地通过 RPC 调用 QueryInterface
【发布时间】:2011-08-26 07:48:52
【问题描述】:

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

【问题讨论】:

  • CreateInstance 返回 S_OK 了吗?
  • @Sam:确实如此。我删除了示例中的检查代码;但会再次放入。
  • COM 接口和 coclass 是否在 Registry 中正确注册?

标签: c++ com rpc inproc


【解决方案1】:

根据你的描述,肯定是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 被正式允许将对象放入与调用者相同的单元中,并且不需要编组,所以你看不到那个奇怪的错误不再编码。

【讨论】:

  • 不错。现在我不必批准我自己的答案 :) 谢谢!
【解决方案2】:

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

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2015-08-24
  • 2019-11-11
  • 1970-01-01
  • 1970-01-01
  • 2011-10-11
  • 1970-01-01
  • 2015-12-08
  • 1970-01-01
相关资源
最近更新 更多