【问题标题】:Invoke marshalled COM interface multiple times多次调用编组的 COM 接口
【发布时间】:2015-07-04 04:19:28
【问题描述】:

我正在编写一个供 JavaScript 使用的 COM 对象。 JavaScript 代码依次在托管的 WebBrowserControl 中运行。我需要从 COM 对象触发一些事件到 JavaScript,这是 Dr. Dobbs 的优秀指南

例如 我的 *.idl 中有以下内容

IJSCallback
{
    void Listen(IDispatch* pJSMethod);
}

JavaScript 方法在 C++ 代码中以IDispatch* 的形式接收,该代码将被存储以供以后从另一个线程调用它。 无论使用何种编组方法(CoMarshalInterThreadInterfaceInStreamIGlobalInterfaceTable),事件触发线程都只能调用 JavaScript 函数一次。之后IDispatch::Invoke() 返回E_ACCESSDENIED

示例 JavaScript 代码

var server = new ActiveXObject("prog_id")
var.Listen(function(ip_add) {
    // ip_add from COM object
});

C++ 线程非常简单。

// called from JavaScript
CMyObject::Listen(IDispatch* pJSMethod)
{
    // IStream* m_pStream;
    CoMarshalInterThreadInterfaceInStream(pJSMethod, IID_IDispatch, &m_pStream);
}

// called from internal C++ thread.
CMyObject::FireEvent()
{
    // IStream* m_pStream;
    // IDispatch* m_pJSMethod;
    CoGetInterfaceAndReleaseStream(m_pStream, IID_IDispatch, (LPVOID*)&m_pJSMethod);

    HSREULT hr = m_pJSMethod->Invoke(...); // hr = S_OK, call is received in JavaScript
    hr = m_pJSMethod->Invoke(...); // hr = E_ACCESSDENIED, call is not received in JavaScript
}

这是预期的行为吗?还是代码有问题?

【问题讨论】:

  • 你的问题是什么?
  • 哦!我还在编辑:)
  • 嗯,函数名中有AndReleaseStream 部分。很明显,你不能在同一个流上调用CoGetInterfaceAndReleaseStream 两次。解组一次,然后缓存结果指针。
  • @IgorTandetnik 我很难理解,加上你的论点即使使用CoUnmarshalInterface也不能解组两次
  • 可以,但必须 a) 将 MSHLFLAGS_TABLESTRONG 标志与 CoMarshalInterface 一起使用,b) 在每次解组后倒回流(CoUnmarshalInterface 将其置于末尾)。

标签: javascript com event-handling dom-events activex


【解决方案1】:

已修复。正如 cmets alert() 中提到的那样,但 document.writeln() 没有。那是因为document.writeln()重置当前文档包括脚本元素,使用document.createElement()document.createTextNode()和朋友修改当前加载的元素。

对于那些熟悉 HTML/JavaScript 的人来说,这可能是常识,对于我们其他人来说,这可能是一个真正的交易。

【讨论】:

    猜你喜欢
    • 2012-12-31
    • 2010-10-18
    • 2010-10-25
    • 2012-01-04
    • 2011-04-05
    • 2022-01-10
    • 1970-01-01
    • 2014-07-02
    • 1970-01-01
    相关资源
    最近更新 更多