【发布时间】:2015-07-04 04:19:28
【问题描述】:
我正在编写一个供 JavaScript 使用的 COM 对象。 JavaScript 代码依次在托管的 WebBrowserControl 中运行。我需要从 COM 对象触发一些事件到 JavaScript,这是 Dr. Dobbs 的优秀指南
例如 我的 *.idl 中有以下内容
IJSCallback
{
void Listen(IDispatch* pJSMethod);
}
JavaScript 方法在 C++ 代码中以IDispatch* 的形式接收,该代码将被存储以供以后从另一个线程调用它。
无论使用何种编组方法(CoMarshalInterThreadInterfaceInStream 或IGlobalInterfaceTable),事件触发线程都只能调用 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