JavaScript调用C++函数

来源:互联网 发布:linux系统如何上网 编辑:程序博客网 时间:2024/06/05 15:15

 上篇介绍了用C++调用JavaScript,这篇反过来说说JS调C++,这样JS和C++沟通的途径就完整了。

首先,实现一个IDispatch接口,当JS调用C++函数时,系统会调用GetIDsOfNames来用函数名取得函数的DISPID,然后调用Invoke完成真正的调用,需要注意的是Invoke的pDispParams中的参数是倒序的。代码如下:

[cpp] view plaincopyprint?
  1. class CExtenalDispatch : public IDispatch  
  2. {  
  3. public:  
  4.     CExtenalDispatch()  
  5.     {  
  6.         m_dwRef = 0;  
  7.     }  
  8.   
  9.     ~CExtenalDispatch()  
  10.     {  
  11.   
  12.     }  
  13.       
  14.     STDMETHOD_(ULONG, AddRef)()  
  15.     {  
  16.         return InterlockedIncrement(&m_dwRef);  
  17.     }  
  18.   
  19.     STDMETHOD_(ULONG, Release)()  
  20.     {  
  21.         unsigned long l = InterlockedDecrement(&m_dwRef);  
  22.         if(l == 0)  
  23.             delete this;  
  24.         return l;  
  25.     }  
  26.   
  27.     STDMETHOD(QueryInterface)(REFIID iid, LPVOID far* ppvObject)  
  28.     {  
  29.         HRESULT hrRet = S_OK;  
  30.         *ppvObject = NULL;  
  31.         if(IsEqualIID(iid, IID_IDispatch))  
  32.             *ppvObject = (IDispatch*)this;  
  33.         else  
  34.             hrRet = E_NOINTERFACE;  
  35.         if (S_OK == hrRet)  
  36.             ((IUnknown*)*ppvObject)->AddRef();  
  37.         return hrRet;  
  38.     }  
  39.   
  40.     STDMETHOD(GetTypeInfoCount)(UINT* pctinfo)  
  41.     {  
  42.         return E_NOTIMPL;  
  43.     }  
  44.   
  45.     STDMETHOD(GetTypeInfo)(/* [in] */ UINT iTInfo,  
  46.         /* [in] */ LCID lcid,  
  47.         /* [out] */ ITypeInfo** ppTInfo)  
  48.     {  
  49.         return E_NOTIMPL;  
  50.     }  
  51.   
  52.     STDMETHOD(GetIDsOfNames)(  
  53.         /* [in] */ REFIID riid,  
  54.         /* [size_is][in] */ LPOLESTR *rgszNames,  
  55.         /* [in] */ UINT cNames,  
  56.         /* [in] */ LCID lcid,  
  57.         /* [size_is][out] */ DISPID *rgDispId)  
  58.     {  
  59.         HRESULT hr = S_OK;  
  60.         for (int i = 0; i < (int)cNames; i++)   
  61.         {  
  62.             CString cszName = rgszNames[i];  
  63.             if(cszName == L"myfunction")  
  64.             {  
  65.                 bFind = TRUE;  
  66.                 rgDispId[i] = 1;  
  67.                 break;  
  68.             }  
  69.             else  
  70.             {  
  71.                 // One or more are unknown so set the return code accordingly  
  72.                 hr = ResultFromScode(DISP_E_UNKNOWNNAME);  
  73.                 rgDispId[i] = DISPID_UNKNOWN;  
  74.             }  
  75.   
  76.         }  
  77.         return hr;  
  78.   
  79.     }  
  80.       
  81.     STDMETHOD(Invoke)(  
  82.         /* [in] */ DISPID dispIdMember,  
  83.         /* [in] */ REFIID riid,  
  84.         /* [in] */ LCID lcid,  
  85.         /* [in] */ WORD wFlags,  
  86.         /* [out][in] */ DISPPARAMS  *pDispParams,  
  87.         /* [out] */ VARIANT  *pVarResult,  
  88.         /* [out] */ EXCEPINFO *pExcepInfo,  
  89.         /* [out] */ UINT *puArgErr)  
  90.     {  
  91.         if (!pDispParams)  
  92.             return E_INVALIDARG;  
  93.   
  94.         if(wFlags & DISPATCH_METHOD)  
  95.         {  
  96.             int memberCount = sizeof(mapMember) / sizeof(MemberInfo);  
  97.             switch(dispIdMember)  
  98.             {  
  99.             case 1:  
  100.                 {  
  101.                     MessageBox(L"Hello JS!", L"");  
  102.                     return S_OK;  
  103.                 }  
  104.                 break;  
  105.             default:  
  106.                 return DISP_E_MEMBERNOTFOUND;  
  107.                 break;  
  108.             }  
  109.         }  
  110.         return DISP_E_MEMBERNOTFOUND;  
  111.     }  
  112. private:  
  113.     long            m_dwRef;  
  114. };  

其次,实现一个IDocHostUIHandlerDispatch接口。其中最重要的是GetExternal,它返回一个CExtenalDispatch指针。

[cpp] view plaincopyprint?
  1. class CBrowserHostUIHandlerImpl : public IDispatchImpl<IDocHostUIHandlerDispatch, &IID_IDocHostUIHandlerDispatch, &LIBID_ATLLib>  
  2. {  
  3. public:  
  4.     CBrowserHostUIHandlerImpl()  
  5.     {  
  6.         m_dwRef = 0;  
  7.         m_pDispatch = NULL;  
  8.     }  
  9.   
  10.     ~CBrowserHostUIHandlerImpl()  
  11.     {  
  12.         if(m_pDispatch)  
  13.         {  
  14.             m_pDispatch->Release();  
  15.             m_pDispatch = NULL;  
  16.         }  
  17.     }  
  18.   
  19.     STDMETHOD_(ULONG, AddRef)(){ return InterlockedIncrement(&m_dwRef); }  
  20.     STDMETHOD_(ULONG, Release)()  
  21.     {  
  22.         unsigned long l = InterlockedDecrement(&m_dwRef);  
  23.         if(l == 0)  
  24.             delete this;  
  25.         return l;  
  26.     }  
  27.     STDMETHOD(QueryInterface)(REFIID iid, LPVOID far* ppvObject)  
  28.     {  
  29.         HRESULT hrRet = S_OK;  
  30.         *ppvObject = NULL;  
  31.         if (IsEqualIID(iid, IID_IUnknown))  
  32.             *ppvObject = (IUnknown*)this;  
  33.         else if(IsEqualIID(iid, IID_IDispatch))  
  34.             *ppvObject = (IDispatch*)this;  
  35.         else if (IsEqualIID(iid, __uuidof(IDocHostUIHandler)))  
  36.             *ppvObject = (IDocHostUIHandler*)this;  
  37.         else  
  38.             hrRet = E_NOINTERFACE;  
  39.         if (S_OK == hrRet)  
  40.             ((IUnknown*)*ppvObject)->AddRef();  
  41.         return hrRet;  
  42.     }  
  43.     STDMETHOD(ShowContextMenu)(/* [in] */ DWORD dwID,  
  44.         /* [in] */ DWORD x,  
  45.         /* [in] */ DWORD y,  
  46.         /* [in] */ IUnknown *pcmdtReserved,  
  47.         /* [in] */ IDispatch *pdispReserved,  
  48.         /* [retval][out] */ HRESULT *dwRetVal)  
  49.     {  
  50.         *dwRetVal = S_OK;  
  51.         return S_OK;  
  52.     }  
  53.       
  54.     STDMETHOD(GetHostInfo)(/* [out][in] */ DWORD *pdwFlags, /* [out][in] */ DWORD *pdwDoubleClick)  
  55.     {  
  56.         *pdwFlags = DOCHOSTUIFLAG_DIV_BLOCKDEFAULT | DOCHOSTUIFLAG_CODEPAGELINKEDFONTS | DOCHOSTUIFLAG_THEME | DOCHOSTUIFLAG_SCROLL_NO | DOCHOSTUIFLAG_NO3DBORDER;  
  57.         *pdwDoubleClick = DOCHOSTUIDBLCLK_DEFAULT;  
  58.         return S_OK;  
  59.     }  
  60.   
  61.     STDMETHOD(ShowUI)(/* [in] */ DWORD dwID,  
  62.         /* [in] */ IUnknown *pActiveObject,  
  63.         /* [in] */ IUnknown *pCommandTarget,  
  64.         /* [in] */ IUnknown *pFrame,  
  65.         /* [in] */ IUnknown *pDoc,  
  66.         /* [retval][out] */ HRESULT *dwRetVal)  
  67.     {  
  68.         return S_OK;  
  69.     }  
  70.       
  71.     STDMETHOD(HideUI)(){ return S_OK; }  
  72.     STDMETHOD(UpdateUI)(){ return S_OK; }  
  73.     STDMETHOD(EnableModeless)(/* [in] */ VARIANT_BOOL fEnable){ return S_OK; }  
  74.     STDMETHOD(OnDocWindowActivate)(/* [in] */ VARIANT_BOOL fActivate){ return S_OK; }  
  75.     STDMETHOD(OnFrameWindowActivate)(/* [in] */ VARIANT_BOOL fActivate){ return S_OK; }  
  76.     STDMETHOD(ResizeBorder)(/* [in] */ long left,  
  77.         /* [in] */ long top,  
  78.         /* [in] */ long right,  
  79.         /* [in] */ long bottom,  
  80.         /* [in] */ IUnknown *pUIWindow,  
  81.         /* [in] */ VARIANT_BOOL fFrameWindow)  
  82.     {  
  83.         return S_OK;  
  84.     }  
  85.   
  86.     STDMETHOD(TranslateAccelerator)(/* [in] */ DWORD_PTR hWnd,  
  87.         /* [in] */ DWORD nMessage,  
  88.         /* [in] */ DWORD_PTR wParam,  
  89.         /* [in] */ DWORD_PTR lParam,  
  90.         /* [in] */ BSTR bstrGuidCmdGroup,  
  91.         /* [in] */ DWORD nCmdID,  
  92.         /* [retval][out] */ HRESULT *dwRetVal)  
  93.     {  
  94.         return S_FALSE;  
  95.     }  
  96.   
  97.     STDMETHOD(GetOptionKeyPath)(/* [out] */ BSTR *pbstrKey, /* [in] */ DWORD dw){ return S_FALSE;}  
  98.     STDMETHOD(GetDropTarget)(/* [in] */ IUnknown *pDropTarget,/* [out] */ IUnknown **ppDropTarget){ return S_FALSE; }  
  99.   
  100.     STDMETHOD(GetExternal)(/* [out] */ IDispatch **ppDispatch)  
  101.     {  
  102.         if(!m_pDispatch)  
  103.         {  
  104.             m_pDispatch = new CExtenalDispatch;  
  105.         }  
  106.         m_pDispatch->AddRef();  
  107.         *ppDispatch = m_pDispatch;  
  108.         return S_OK;  
  109.     }  
  110.     STDMETHOD(TranslateUrl)(/* [in] */ DWORD dwTranslate, /* [in] */ BSTR bstrURLIn, /* [out] */ BSTR *pbstrURLOut){ return S_FALSE; }  
  111.     STDMETHOD(FilterDataObject)(/* [in] */ IUnknown *pDO, /* [out] */ IUnknown **ppDORet){ return S_FALSE; }  
  112. private:  
  113.     long            m_dwRef;  
  114.     CExtenalDispatch * m_pDispatch;   
  115. };  

 

最后,在WebBrowser控制创建好后,调用SetExternalUIHandler。如下:

[cpp] view plaincopyprint?
  1. CBrowserHostUIHandlerImpl * pHost = new CBrowserHostUIHandlerImpl;  
  2. pHost->AddRef();  
  3. SetExternalUIHandler(pHost);  

来源 :http://blog.csdn.net/yyan/article/details/4814866
原创粉丝点击