zoukankan      html  css  js  c++  java
  • C++代码中回调JS方法

    前段时间开发了一个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方法实现。

    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>
  • 相关阅读:
    良心之作送你几个Xsheel使用小技巧
    面试问Redis集群,被虐的不行了......
    一文搞定Redis五大数据类型及应用场景
    写给大忙人的Redis主从复制,花费五分钟让你面试不尴尬
    Redis删除策略和逐出策略
    一文带你了解Redis持久化完整版本
    MySQL--创建计算字段
    MySQL语句与正则表达式
    SQLZOO练习二--SELECT from Nobel Tutorial
    SQLZOO练习(一)SELECT BASICS,SELECT form world
  • 原文地址:https://www.cnblogs.com/wadexia/p/COM-JS.html
Copyright © 2011-2022 走看看