C++和JavaScript脚本的相互调用
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了C++和JavaScript脚本的相互调用,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含13876字,纯文字阅读大概需要20分钟。
内容图文
![C++和JavaScript脚本的相互调用](/upload/InfoBanner/zyjiaocheng/727/aa4a415db7074e94bc73ef2a8cd7d4e4.jpg)
脚本调用C++相对比较容易,使用ATL组件只需要抛双接口即可,但在exe里如何做到呢?本文实现了在exe里脚本和C++的相互调用.在EXE里也需要对外抛送一个继承自IDispatch的接口.并需要重载它的所有接口。由于水平有限,所以难免有错。
?//?头文件
?static?const?GUID?IID_CExternal?=
?{?0x52fee9af,?0xb3b3,?0x4756,?{?0x80,?0x10,?0xfe,?0xa8,?0xf9,?0xfd,?0xd3,?0x3f?}?};
?
?
?class?CExternal:public?IDispatch
?{
?public:
?????CExternal(HWND?h);
?????virtual?~CExternal();
?????ULONG?__stdcall?AddRef()?{?return?1;?}
?????ULONG?__stdcall?Release()?{???return?1;?}
?
???????HRESULT?__stdcall?QueryInterface(REFIID?riid,?void?FAR*?FAR*?ppv)
???????{
??????????if?(ppv?==?NULL)
?????????????return?E_POINTER;
??????????*ppv?=?NULL;
??????????if?(InlineIsEqualGUID(riid,?IID_IUnknown))
??????????{
?????????????*ppv?=?static_cast<IUnknown?*>(this);
?????????????return?S_OK;
??????????}
??????????if(InlineIsEqualGUID(riid,?IID_IDispatch)?)
??????????{
?????????????*ppv?=?static_cast<IDispatch?FAR?*>(this);
?????????????return?S_OK;
??????????}
??????????if(InlineIsEqualGUID(riid,?IID_CExternal)?)
??????????{
?????????????*ppv?=?static_cast<CExternal?*>(this);
?????????????return?S_OK;
??????????}
??????????return?E_NOINTERFACE;
???????}
?
?????HRESULT?__stdcall?GetTypeInfoCount(UINT?FAR*?pctinfo)
?????{
???????if?(pctinfo?==?NULL)
???????{
?????????return?E_INVALIDARG;
????????}
???????//?there?is?only?one?function
????????*pctinfo?=?1;
????????return?NOERROR;
???????}
?
???????HRESULT?__stdcall?GetTypeInfo(UINT?iTInfo,LCID?lcid,ITypeInfo?FAR*?FAR*?ppTInfo)
???????{
??????????if?(ppTInfo?==?NULL)
?????????????return?E_INVALIDARG;
??????????*ppTInfo?=?NULL;
??????????if?(iTInfo?!=?0)
?????????????return?DISP_E_BADINDEX;
??????????*ppTInfo?=?m_typeinfo;
??????????if?(m_typeinfo!=NULL)
?????????????m_typeinfo->AddRef();
??????????return?NOERROR;
???????}
?
???????HRESULT?__stdcall?GetIDsOfNames(REFIID??riid,OLECHAR?FAR*?FAR*?rgszNames,?unsigned?int??cNames,??LCID???lcid,DISPID?FAR*rgdispid)
???????{
??????????if(lstrcmpiW(*rgszNames,L"exec")==0)
??????????{
?????????????*rgdispid=0;
?????????????return?S_OK;
??????????}
??????????return?E_FAIL;
???????}
?
???????HRESULT?__stdcall?Invoke(DISPID?dispidMember,REFIID?riid,LCID?lcid,WORD?wFlags,DISPPARAMS?FAR*?pdispparams,VARIANT?FAR*?pvarResult,EXCEPINFO?FAR*?pexcepinfo,UINT?FAR*?puArgErr)
???????{
??????????if((DISPATCH_PROPERTYGET&wFlags?||?DISPATCH_METHOD&wFlags)
?????????????&&?dispidMember==0)
??????????{
?????????????CComBSTR?sRet;
?????????????exec(pdispparams,?&sRet);
?????????????if?(DISPATCH_PROPERTYGET&wFlags)
?????????????{
????????????????pvarResult->vt=VT_BSTR;
????????????????pvarResult->bstrVal=sRet.Detach();
?????????????}
?????????????return?S_OK;
??????????}
??????????return?E_FAIL;
???????}
????????HRESULT??__stdcall?exec(DISPPARAMS?FAR*?pdispparams,?BSTR??*pbstrValue);
?
?private:
??HWND?m_hWnd;
??LPTYPEINFO??m_typeinfo;
??CString?GetVariantStr(VARIANT?vVal);
?};
?
?//?实现的文件
?CExternal::CExternal(HWND?h)
?{
??csDisplayStr?=?"";
??m_typeinfo?=NULL;
??m_hWnd?=?h;
??//?Create?an?exec?function
??static?PARAMDATA??PARAM_VALUE[]={{OLESTR("fnName"),VT_BSTR},{OLESTR("p1"),VT_BSTR}};
??static?METHODDATA??rgmdataCCalc={OLESTR("exec"),PARAM_VALUE,0,0,CC_CDECL,2,DISPATCH_METHOD|DISPATCH_PROPERTYGET,VT_BSTR};
??static?INTERFACEDATA?ifdata={&rgmdataCCalc,?1};
??HRESULT?hres=CreateDispTypeInfo(&ifdata,?LOCALE_SYSTEM_DEFAULT,?&m_typeinfo);
?
?}
?CString?CExternal::GetVariantStr(VARIANT?vVal)
?{
????CString?csReVal;
?
?
????switch?(vVal.vt)
????{
???????case?VT_BOOL:
???????{
??????????if?(vVal.boolVal?==?VARIANT_TRUE)
??????????{
?????????????return("1");
??????????}
??????????else
??????????{
?????????????return("0");
??????????}
??????????break;
?
???????}
???????case?VT_I2:
???????{
??????????csReVal.Format("%d",vVal.iVal);
??????????return(csReVal);
???????}
?
???????case?VT_I4:
???????{
??????????csReVal.Format("%d",vVal.lVal);
??????????return(csReVal);
???????}
?
?//??????case?VT_R8:
?//??????{
?//?????????//csReVal.Format("%f",vVal.dblVal);
?//?????????csReVal=vVal.dblVal;
?//?????????return(csReVal);
?//??????}
?
?
???????case?VT_BSTR:
???????{
?
??????????return(CString(vVal.bstrVal));
???????}
????}
???????return?"";
?}
?
?HRESULT??__stdcall?CExternal::exec(DISPPARAMS?FAR*?pdispparams,?BSTR??*pbstrValue)?//?脚本的入口点
?{
????//??no?argument?return
????if?(pdispparams->cArgs?<?1)
????{
???????*pbstrValue?=?bstrRet.Detach();
???????return?S_OK;
????}
????int?args?=?pdispparams->cArgs;
?
????//?C?calling?convention?order?of?parameters?is?in?reversed
????CString?action?=?pdispparams->rgvarg[args-1].bstrVal;
????debugIt("?exec***action:%s:%d?",action,args);
????if?(action?==?"alert")
????{
?????????CString?csMessage;
?????????CString?csTitle;
?
?????????if?(args?>?1)
?????????{
?????????????csMessage=??GetVariantStr(pdispparams->rgvarg[args-2]);
?????????}
?????????if?(args?>?2)
?????????{
?????????????csTitle?=?GetVariantStr(pdispparams->rgvarg[args-3]);
?????????}
???????MessageBox(m_hWnd,?LPCSTR(csMessage),?LPCSTR(csTitle),?MB_OK);
????}
?//else?if(action?==?"什么")
?//{
?//}
??????*pbstrValue=bstrRet.Detach();?//?返回值
????return?S_OK;
?}
?
?
?CExternal::~CExternal()
?{
??if(m_typeinfo)?m_typeinfo->Release();
?}
?
C++调用脚本可以使用下面的代码,此代码是我在网上下载的,具体的来源我已经不记得了,但在网上应该可以找到类似的.原理是用到了WebBrowser2,但是C++和脚本的相互调用都用到了HTML页面,使用HTML页面成了包袱,能否丢掉它,我不知道如何实现,望高手指点.......
?//?头文件
?#pragma?once
?#include?<atlbase.h>
?#include?<Mshtml.h>
?
?class?CCallScript
?{
?public:
?????CCallScript();
?????virtual?~CCallScript();
?????BOOL?DocumentSet(){return(m_bDocumentSet);}
?????BOOL?SetDocument(IDispatch*?pDisp);
?????LPDISPATCH?GetHtmlDocument()?const;
?????const?CComBSTR?GetLastError()?const;
?????BOOL?GetScript(CComPtr<IDispatch>&?spDisp);
?????BOOL?GetScripts(CComPtr<IHTMLElementCollection>&?spColl);
?
?????BOOL?Run(const?CComBSTR?strFunc,CComVariant*?pVarResult?=?NULL);
?????BOOL?Run(const?CComBSTR?strFunc,const?CComBSTR?strArg1,CComVariant*?pVarResult?=?NULL);
?????BOOL?Run(const?CComBSTR?strFunc,const?CComBSTR?strArg1,const?CComBSTR?strArg2,CComVariant*?pVarResult?=?NULL);
?????BOOL?Run(const?CComBSTR?strFunc,const?CComBSTR?strArg1,const?CComBSTR?strArg2,const?CComBSTR?strArg3,CComVariant*?pVarResult?=?NULL);
?????BOOL?Run(const?CComBSTR?strFunc,const?CSimpleArray<CComBSTR>?&?paramArray,CComVariant*?pVarResult?=?NULL);
?private:
?????BOOL?m_bDocumentSet;
?protected:
?
?
?????void?ShowError(CComBSTR?lpszText);
?
?protected:
?
?????CComPtr<IHTMLDocument2>????m_spDoc;
?????CComBSTR????m_strError;
?};
?
?inline?void?CCallScript::ShowError(CComBSTR?lpszText)
?{
?????m_strError?=?"Error:?";
?????m_strError.Append(lpszText);
?}
?inline?const?CComBSTR?CCallScript::GetLastError()?const
?{
?????return?m_strError;
?}
?inline?LPDISPATCH?CCallScript::GetHtmlDocument()?const
?{
?????return?m_spDoc;
?}
?//?CPP文件
?#include?"stdafx.h"
?#include?"CallScript.h"
?
?#define?CHECK_POINTER(p)
?????ATLASSERT(p?!=?NULL);
?????if(p?==?NULL)
?????{
?????????ShowError("NULL?pointer");
?????????return?FALSE;
?????}
?
?const?CComBSTR?GetSystemErrorMessage(DWORD?dwError)
?{
?????CComBSTR?strError;
?????LPTSTR?lpBuffer;
?
?????if(!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER?|?FORMAT_MESSAGE_FROM_SYSTEM,
?????????????NULL,??dwError,
?????????????MAKELANGID(LANG_NEUTRAL,?SUBLANG_SYS_DEFAULT),
?????????????(LPTSTR)?&lpBuffer,?0,?NULL))
?
?????{
?????????strError?=?"FormatMessage?Netive?Error"?;
?????}
?????else
?????{
?????????strError?=?lpBuffer;
?????????LocalFree(lpBuffer);
?????}
?????return?strError;
?}
?
?CCallScript::CCallScript()
?{
?????m_bDocumentSet?=?FALSE;
?
?}
?
?CCallScript::~CCallScript()
?{
?
?}
?
?BOOL?CCallScript::SetDocument(IDispatch*?pDisp)
?{
?????CHECK_POINTER(pDisp);
?
?????m_spDoc?=?NULL;
?
?????CComPtr<IDispatch>?spDisp?=?pDisp;
?
?????HRESULT?hr?=?spDisp->QueryInterface(IID_IHTMLDocument2,(void**)&m_spDoc);
?????if(FAILED(hr))
?????{
?????????ShowError("Failed?to?get?HTML?document?COM?object");
?????????return?FALSE;
?????}
?????m_bDocumentSet?=?TRUE;
?????return?TRUE;
?}
?
?BOOL?CCallScript::GetScript(CComPtr<IDispatch>&?spDisp)
?{
?????CHECK_POINTER(m_spDoc);
?????HRESULT?hr?=?m_spDoc->get_Script(&spDisp);
?????ATLASSERT(SUCCEEDED(hr));
?????return?SUCCEEDED(hr);
?}
?
?BOOL?CCallScript::GetScripts(CComPtr<IHTMLElementCollection>&?spColl)
?{
?????CHECK_POINTER(m_spDoc);
?????HRESULT?hr?=?m_spDoc->get_scripts(&spColl);
?????ATLASSERT(SUCCEEDED(hr));
?????return?SUCCEEDED(hr);
?}
?
?BOOL?CCallScript::Run(const?CComBSTR?strFunc,CComVariant*?pVarResult)
?{
?????CSimpleArray<CComBSTR>??paramArray;
?????return?Run(strFunc,paramArray,pVarResult);
?}
?
?BOOL?CCallScript::Run(const?CComBSTR?strFunc,const?CComBSTR?strArg1,CComVariant*?pVarResult)
?{
?????CSimpleArray<CComBSTR>??paramArray;
?????paramArray.Add((CComBSTR?&)strArg1);
?????return?Run(strFunc,paramArray,pVarResult);
?}
?
?BOOL?CCallScript::Run(const?CComBSTR?strFunc,const?CComBSTR?strArg1,const?CComBSTR?strArg2,CComVariant*?pVarResult)
?{
?????CSimpleArray<CComBSTR>??paramArray;
?????paramArray.Add((CComBSTR?&)strArg1);
?????paramArray.Add((CComBSTR?&)strArg2);
?????return?Run(strFunc,paramArray,pVarResult);
?}
?
?BOOL?CCallScript::Run(const?CComBSTR?strFunc,const?CComBSTR?strArg1,const?CComBSTR?strArg2,const?CComBSTR?strArg3,CComVariant*?pVarResult)
?{
?????CSimpleArray<CComBSTR>??paramArray;
?????paramArray.Add((CComBSTR?&)strArg1);
?????paramArray.Add((CComBSTR?&)strArg2);
?????paramArray.Add((CComBSTR?&)strArg3);
?????return?Run(strFunc,paramArray,pVarResult);
?}
?
?BOOL?CCallScript::Run(const?CComBSTR?strFunc,?const?CSimpleArray<CComBSTR>&?paramArray,CComVariant*?pVarResult)
?{
?????CComPtr<IDispatch>?spScript;
?????if(!GetScript(spScript))
?????{
?????????ShowError("Cannot?GetScript");
?????????return?FALSE;
?????}
?????CComBSTR?bstrMember(strFunc);
?????DISPID?dispid?=?NULL;
?????HRESULT?hr?=?spScript->GetIDsOfNames(IID_NULL,&bstrMember,1,
?????????????????????????????????????????????LOCALE_SYSTEM_DEFAULT,&dispid);
?????if(FAILED(hr))
?????{
?????????ShowError(GetSystemErrorMessage(hr));
?????????return?FALSE;
?????}
?
?????//const?int?arraySize?=?paramArray.GetCount();
?????const?int?arraySize?=?paramArray.GetSize();
?
?????DISPPARAMS?dispparams;
?????memset(&dispparams,?0,?sizeof?dispparams);
?????dispparams.cArgs?=?arraySize;
?????dispparams.rgvarg?=?new?VARIANT[dispparams.cArgs];
?????//__asm?{int?3}
?????CComBSTR?bstr;
?????for(?int?i?=?0;?i?<?arraySize;?i++)
?????{
?????????bstr.Empty();
?????????//CComBSTR?bstr?=?paramArray.GetAt(arraySize?-?1?-?i);?//?back?reading
?????????bstr?=?paramArray[arraySize?-?1?-?i];?//?back?reading
?????????//bstr.CopyTo(&dispparams.rgvarg[i].bstrVal);?//memory?leak
?????????dispparams.rgvarg[i].bstrVal?=?bstr.m_str;?//also?cause?problem?when?paras?are?more?than?1
?????????dispparams.rgvarg[i].vt?=?VT_BSTR;
?????}
?????dispparams.cNamedArgs?=?0;
?
?????EXCEPINFO?excepInfo;
?????memset(&excepInfo,?0,?sizeof?excepInfo);
????????CComVariant?vaResult;
?????UINT?nArgErr?=?(UINT)-1;??//?initialize?to?invalid?arg
?
?????hr?=?spScript->Invoke(dispid,IID_NULL,0,
?????????????????????????????DISPATCH_METHOD,&dispparams,&vaResult,&excepInfo,&nArgErr);
?
?///////////////?bug?fix?memory?leak?code?start?///////////////
?//????for(?int?j?=?0;?j?<?arraySize;?j++)
?//????????::SysFreeString(dispparams.rgvarg[j].bstrVal);
?///////////////?bug?fix?memory?leak?code?end?///////////////
?
?????delete?[]?dispparams.rgvarg;
?????if(FAILED(hr))
?????{
?????????ShowError(GetSystemErrorMessage(hr));
?????????return?FALSE;
?????}
?
?????if(pVarResult)
?????{
?????????*pVarResult?=?vaResult;
?????}
?????return?FALSE;
?}
?
这两个文件的使用的方法:
?????//?Get?the?browser?control.
?????CAxWindow?wnd?=?GetDlgItem(IDC_EXPLORER);?//?WebBrowser
?????wnd.QueryControl(?&m_spBrowser?);
?????CComPtr<IAxWinAmbientDispatch>?spAmbient;
?????HRESULT?hr?=?wnd.QueryHost(&spAmbient);
?
?????//?diable?the?context?menu
?????//?disable?the?scrollbar
?????if(?SUCCEEDED(hr)?)
?????{
?????????spAmbient->put_AllowContextMenu(VARIANT_TRUE);
?????????spAmbient->put_DocHostFlags(docHostUIFlagFLAT_SCROLLBAR);
?????}
?
?????//?navigate?to?the?base?html
?????VARIANT?flag?=?{0};
?????VARIANT?name?=?{0};
?????VARIANT?post?=?{0};
?????VARIANT?head?=?{0};
?????//?
?//????m_spBrowser->Navigate(_bstr_t(GetFullName("WhizConsoleSlave.html")),?&flag,?&name,?&post,?&head);
?????TCHAR?szFileName[MAX_PATH];
?????::GetModuleFileName(_Module.GetModuleInstance(),?szFileName,?MAX_PATH);
?????TCHAR?szRes[MAX_PATH+10];
?????::wsprintf(szRes,?_T("res://%s/%0d"),?szFileName,?IDR_HTML);
?????CComVariant?vURL(szRes);
?????m_spBrowser->Navigate2(&vURL,?&flag,?&name,?&post,?&head);?//?显示指定的页面
?
?????//?Create?a?wrapper?about?the?external?dispatch?interface
?????CComObject<CWrapperDispatch>*???spdispWrapper?=?0;
?????hr?=?CComObject<CWrapperDispatch>::CreateInstance(&spdispWrapper);
?????if(?FAILED(hr)?)?return?0;
?
?????//?Dummy?for?refcount?management
?????CComPtr<IUnknown>?spUnk?=?spdispWrapper;
?
?????//?Create?the?object?that?will?handle?the?external?interface?for?the
?????//?html?file.
?????pExternal?=?new?CExternal(m_hWnd);
?????m_oExternal?=?static_cast<IDispatch?*>(pExternal);
?
?????//?Set?the?external?dispatch?interface
?????spdispWrapper->SetDispatch(m_oExternal);?//?对脚本抛送接口
?????hr?=?wnd.SetExternalDispatch(spdispWrapper);
?//????wnd.SetFocus();
?
?
?//?******************************************************************
?//?调用脚本比较容易
?????if?(?m_CallScript.DocumentSet()?==?FALSE)
?????{
?????????IDispatch*?d?=?NULL;
?????????m_spBrowser->get_Document(&d);
?????????m_CallScript.SetDocument(d);
?????????d->Release();
?????}
?????m_CallScript.Run(L"DisplayStr");?//?DisplayStr就是脚本的函数
?????m_CallScript.Run(L"AddDir","a","b");?//?AddDir也是脚本的函数,a和b是AddDir的参数.
?
?
内容总结
以上是互联网集市为您收集整理的C++和JavaScript脚本的相互调用全部内容,希望文章能够帮你解决C++和JavaScript脚本的相互调用所遇到的程序开发问题。
如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
来源:【匿名】