副标题#e#
前段时间开拓了一个COM组件共同web前端利用,碰着了C++中挪用JS代码的问题,在网上查了许多资料,现 总结一下,留作今后察看。
C++中挪用JS代码主要有两种环境:1. IE线程中挪用;2. 其他线程挪用
1. IE线程中挪用:这种环境网上已经有许多资料,下面列出示列代码:
C++代码
STDMETHODIMP CJsInvoker::InvokeJsFunc(LONG para1, LONG para2, VARIANT jsFunction, LONG* retValue) { CComPtr<IDispatch> jsCallback; if (jsFunction.vt == VT_DISPATCH) jsCallback = jsFunction.pdispVal; VARIANT arg[2]; arg[0].vt = VT_I4; arg[1].vt = VT_I4; arg[0].lVal = para1; arg[1].lVal = para2; VARIANT pvarRet; jsCallback.InvokeN(static_cast<DISPID>(DISPID_VALUE), arg, 2, &pvarRet); *retValue = pvarRet.lVal; return S_OK; }
JS代码
<script type="text/javascript"> // 两个参数的回调要领 function jsCallbackFunc(a, b) { return a + b; } var obj = new ActiveXObject("ComCallJsFunction.JsInvoker"); var retValue = objA.InvokeJsFunc(1, 2, jsCallbackFunc); alert(retValue); // 返回值为3 </script>
从代码中可以看出,Js要领作为IDispatch指针传入COM,C++通过挪用其InvokeN 要领实现。
#p#副标题#e#
2. 其他线程挪用:与IE线程直接挪用的区别在于需要列集与反列集,原因是JS代码是运行 在本身的套间线程里的,其他线程是不能直接会见的,只能通过署理进入动静轮回中。
C++代码
STDMETHODIMP CJsInvoker::InvokeJsFunc3(LONG para1, LONG para2, VARIANT jsFunction, LONG* retValue) { // Check whether is valid Dispatch interface. if (V_VT(&jsFunction) != VT_DISPATCH || jsFunction.pdispVal == NULL) { return E_INVALIDARG; } // 对IDispatch指针列集 CoMarshalInterThreadInterfaceInStream(IID_IDispatch, jsFunction.pdispVal, &m_stream_jsfunc); m_hTread = CreateThread(NULL, 0, ThreadFunction, this, NULL, NULL); return S_OK; } DWORD WINAPI ThreadFunction(LPVOID pParam) { ::CoInitialize(NULL); CJsInvoker* pJsInvoker = (CJsInvoker*)pParam; CComPtr<IDispatch> script; // 反列集获得IDisPatch指针 CoGetInterfaceAndReleaseStream(pJsInvoker->m_stream_jsfunc, IID_IDispatch, (LPVOID *) &script); VARIANT arg[2]; arg[0].vt = VT_I4; arg[1].vt = VT_I4; arg[0].lVal = 1; arg[1].lVal = 2; VARIANT pvarRet; script.InvokeN(static_cast<DISPID>(DISPID_VALUE), arg, 2, &pvarRet); ::CoUninitialize(); return S_OK; }
JS代码
<script type="text/javascript"> // 两个参数的回调要领 function jsCallbackFunc(a, b) { return a + b; } var obj = new ActiveXObject("ComCallJsFunction.JsInvoker"); var retValue = objA.InvokeJsFunc(1, 2, jsCallbackFunc); alert(retValue); // 此时返回值没有意义 </script>