如何实现C语言与JavaScript脚本之间的有效互调?

2026-04-16 20:423阅读0评论SEO基础
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1613个文字,预计阅读时间需要7分钟。

如何实现C语言与JavaScript脚本之间的有效互调?

在exe文件中实现脚本和C++的相互调用,可以通过以下步骤进行:

1. 封装脚本接口:首先,需要将脚本的功能封装成一个接口。在脚本中定义一个继承自IDispatch的接口,以便在C++中调用。

2. 创建脚本组件:使用ATL(Active Template Library)或类似工具创建一个脚本组件。在组件中实现封装的接口。

3. 注册COM接口:确保脚本组件的COM接口被正确注册,以便C++代码可以访问。

4. C++调用脚本: - 在C++代码中,使用COM库(如COMDLG32.DLL)创建一个脚本组件的实例。 - 使用IDispatch接口调用脚本中的方法。

如何实现C语言与JavaScript脚本之间的有效互调?

5. 实现脚本与C++的交互: - 在C++中,声明一个指向IDispatch的指针。 - 使用脚本组件的实例初始化这个指针。 - 通过IDispatch指针调用脚本中的方法。

6. 传递参数: - 在调用脚本方法时,可以通过VARIANT类型传递参数。 - 如果需要从脚本传递回C++,同样使用VARIANT类型接收。

7. 示例代码: cpp // C++ 代码示例 #include #include

CoInitialize(); IUnknown* pUnk=NULL; HRESULT hr=CoCreateInstance(CLSID_ScriptComponent, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (LPVOID*)&pUnk); if (SUCCEEDED(hr)) { IDispatch* pDisp=NULL; hr=pUnk->QueryInterface(IID_IDispatch, (LPVOID*)&pDisp); if (SUCCEEDED(hr)) { VARIANT vtResult; vtResult.vt=VT_EMPTY; DISPID dispId=DISPID_PROPERTYGET; hr=pDisp->Invoke(dispId, IID_IDispatch, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &vtResult, NULL, NULL, NULL); if (SUCCEEDED(hr)) { // 处理返回结果 } pDisp->Release(); } pUnk->Release(); } CoUninitialize();

8. 资源管理:确保在C++代码中正确管理COM对象的引用计数,避免内存泄漏。

通过以上步骤,可以在exe文件中实现脚本和C++的相互调用,并传递必要的参数。

脚本调用C++相对比较容易,使用ATL组件只需要抛双接口即可,但在exe里如何做到呢?本文实现了在exe里脚本和C++的相互调用.在EXE里也需要对外抛送一个继承自IDispatch的接口.并需要重载它的所有接口。由于水平有限,所以难免有错。 //头文件 staticconstGUIDIID_CExternal= {0x52fee9af,0xb3b3,0x4756,{0x80,0x10,0xfe,0xa8,0xf9,0xfd,0xd3,0x3f}}; classCExternal:publicIDispatch { public: CExternal(HWNDh); virtual~CExternal(); ULONG__stdcallAddRef(){return1;} ULONG__stdcallRelease(){return1;} HRESULT__stdcallQueryInterface(REFIIDriid,voidFAR*FAR*ppv) { if(ppv==NULL) returnE_POINTER; *ppv=NULL; if(InlineIsEqualGUID(riid,IID_IUnknown)) { *ppv=static_cast<IUnknown*>(this); returnS_OK; } if(InlineIsEqualGUID(riid,IID_IDispatch)) { *ppv=static_cast<IDispatchFAR*>(this); returnS_OK; } if(InlineIsEqualGUID(riid,IID_CExternal)) { *ppv=static_cast<CExternal*>(this); returnS_OK; } returnE_NOINTERFACE; } HRESULT__stdcallGetTypeInfoCount(UINTFAR*pctinfo) { if(pctinfo==NULL) { returnE_INVALIDARG; } //thereisonlyonefunction *pctinfo=1; returnNOERROR; } HRESULT__stdcallGetTypeInfo(UINTiTInfo,LCIDlcid,ITypeInfoFAR*FAR*ppTInfo) { if(ppTInfo==NULL) returnE_INVALIDARG; *ppTInfo=NULL; if(iTInfo!=0) returnDISP_E_BADINDEX; *ppTInfo=m_typeinfo; if(m_typeinfo!=NULL) m_typeinfo->AddRef(); returnNOERROR; } HRESULT__stdcallGetIDsOfNames(REFIIDriid,OLECHARFAR*FAR*rgszNames,unsignedintcNames,LCIDlcid,DISPIDFAR*rgdispid) { if(lstrcmpiW(*rgszNames,L"exec")==0) { *rgdispid=0; returnS_OK; } returnE_FAIL; } HRESULT__stdcallInvoke(DISPIDdispidMember,REFIIDriid,LCIDlcid,WORDwFlags,DISPPARAMSFAR*pdispparams,VARIANTFAR*pvarResult,EXCEPINFOFAR*pexcepinfo,UINTFAR*puArgErr) { if((DISPATCH_PROPERTYGET&wFlags||DISPATCH_METHOD&wFlags) &&dispidMember==0) { CComBSTRsRet; exec(pdispparams,&sRet); if(DISPATCH_PROPERTYGET&wFlags) { pvarResult->vt=VT_BSTR; pvarResult->bstrVal=sRet.Detach(); } returnS_OK; } returnE_FAIL; } HRESULT__stdcallexec(DISPPARAMSFAR*pdispparams,BSTR*pbstrValue); private: HWNDm_hWnd; LPTYPEINFOm_typeinfo; CStringGetVariantStr(VARIANTvVal); }; //实现的文件 CExternal::CExternal(HWNDh) { csDisplayStr=""; m_typeinfo=NULL; m_hWnd=h; //Createanexecfunction staticPARAMDATAPARAM_VALUE[]={{OLESTR("fnName"),VT_BSTR},{OLESTR("p1"),VT_BSTR}}; staticMETHODDATArgmdataCCalc={OLESTR("exec"),PARAM_VALUE,0,0,CC_CDECL,2,DISPATCH_METHOD|DISPATCH_PROPERTYGET,VT_BSTR}; staticINTERFACEDATAifdata={&rgmdataCCalc,1}; HRESULThres=CreateDispTypeInfo(&ifdata,LOCALE_SYSTEM_DEFAULT,&m_typeinfo); } CStringCExternal::GetVariantStr(VARIANTvVal) { CStringcsReVal; switch(vVal.vt) { caseVT_BOOL: { if(vVal.boolVal==VARIANT_TRUE) { return("1"); } else { return("0"); } break; } caseVT_I2: { csReVal.Format("%d",vVal.iVal); return(csReVal); } caseVT_I4: { csReVal.Format("%d",vVal.lVal); return(csReVal); } //caseVT_R8: //{ ////csReVal.Format("%f",vVal.dblVal); //csReVal=vVal.dblVal; //return(csReVal); //} caseVT_BSTR: { return(CString(vVal.bstrVal)); } } return""; } HRESULT__stdcallCExternal::exec(DISPPARAMSFAR*pdispparams,BSTR*pbstrValue)//脚本的入口点 { //noargumentreturn if(pdispparams->cArgs<1) { *pbstrValue=bstrRet.Detach(); returnS_OK; } intargs=pdispparams->cArgs; //Ccallingconventionorderofparametersisinreversed CStringaction=pdispparams->rgvarg[args-1].bstrVal; debugIt("exec***action:%s:%d",action,args); if(action=="alert") { CStringcsMessage; CStringcsTitle; 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); } //elseif(action=="什么") //{ //} *pbstrValue=bstrRet.Detach();//返回值 returnS_OK; } CExternal::~CExternal() { if(m_typeinfo)m_typeinfo->Release(); } C++调用脚本可以使用下面的代码,此代码是我在网上下载的,具体的来源我已经不记得了,但在网上应该可以找到类似的.原理是用到了WebBrowser2,但是C++和脚本的相互调用都用到了HTML页面,使用HTML页面成了包袱,能否丢掉它,我不知道如何实现,望高手指点....... //头文件 #pragmaonce #include<atlbase.h> #include<Mshtml.h> classCCallScript { public: CCallScript(); virtual~CCallScript(); BOOLDocumentSet(){return(m_bDocumentSet);} BOOLSetDocument(IDispatch*pDisp); LPDISPATCHGetHtmlDocument()const; constCComBSTRGetLastError()const; BOOLGetScript(CComPtr<IDispatch>&spDisp); BOOLGetScripts(CComPtr<IHTMLElementCollection>&spColl); BOOLRun(constCComBSTRstrFunc,CComVariant*pVarResult=NULL); BOOLRun(constCComBSTRstrFunc,constCComBSTRstrArg1,CComVariant*pVarResult=NULL); BOOLRun(constCComBSTRstrFunc,constCComBSTRstrArg1,constCComBSTRstrArg2,CComVariant*pVarResult=NULL); BOOLRun(constCComBSTRstrFunc,constCComBSTRstrArg1,constCComBSTRstrArg2,constCComBSTRstrArg3,CComVariant*pVarResult=NULL); BOOLRun(constCComBSTRstrFunc,constCSimpleArray<CComBSTR>&paramArray,CComVariant*pVarResult=NULL); private: BOOLm_bDocumentSet; protected: voidShowError(CComBSTRlpszText); protected: CComPtr<IHTMLDocument2>m_spDoc; CComBSTRm_strError; }; inlinevoidCCallScript::ShowError(CComBSTRlpszText) { m_strError="Error:"; m_strError.Append(lpszText); } inlineconstCComBSTRCCallScript::GetLastError()const { returnm_strError; } inlineLPDISPATCHCCallScript::GetHtmlDocument()const { returnm_spDoc; } //CPP文件 #include"stdafx.h" #include"CallScript.h" #defineCHECK_POINTER(p) ATLASSERT(p!=NULL); if(p==NULL) { ShowError("NULLpointer"); returnFALSE; } constCComBSTRGetSystemErrorMessage(DWORDdwError) { CComBSTRstrError; LPTSTRlpBuffer; if(!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, NULL,dwError, MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT), (LPTSTR)&lpBuffer,0,NULL)) { strError="FormatMessageNetiveError"; } else { strError=lpBuffer; LocalFree(lpBuffer); } returnstrError; } CCallScript::CCallScript() { m_bDocumentSet=FALSE; } CCallScript::~CCallScript() { } BOOLCCallScript::SetDocument(IDispatch*pDisp) { CHECK_POINTER(pDisp); m_spDoc=NULL; CComPtr<IDispatch>spDisp=pDisp; HRESULThr=spDisp->QueryInterface(IID_IHTMLDocument2,(void**)&m_spDoc); if(FAILED(hr)) { ShowError("FailedtogetHTMLdocumentCOMobject"); returnFALSE; } m_bDocumentSet=TRUE; returnTRUE; } BOOLCCallScript::GetScript(CComPtr<IDispatch>&spDisp) { CHECK_POINTER(m_spDoc); HRESULThr=m_spDoc->get_Script(&spDisp); ATLASSERT(SUCCEEDED(hr)); returnSUCCEEDED(hr); } BOOLCCallScript::GetScripts(CComPtr<IHTMLElementCollection>&spColl) { CHECK_POINTER(m_spDoc); HRESULThr=m_spDoc->get_scripts(&spColl); ATLASSERT(SUCCEEDED(hr)); returnSUCCEEDED(hr); } BOOLCCallScript::Run(constCComBSTRstrFunc,CComVariant*pVarResult) { CSimpleArray<CComBSTR>paramArray; returnRun(strFunc,paramArray,pVarResult); } BOOLCCallScript::Run(constCComBSTRstrFunc,constCComBSTRstrArg1,CComVariant*pVarResult) { CSimpleArray<CComBSTR>paramArray; paramArray.Add((CComBSTR&)strArg1); returnRun(strFunc,paramArray,pVarResult); } BOOLCCallScript::Run(constCComBSTRstrFunc,constCComBSTRstrArg1,constCComBSTRstrArg2,CComVariant*pVarResult) { CSimpleArray<CComBSTR>paramArray; paramArray.Add((CComBSTR&)strArg1); paramArray.Add((CComBSTR&)strArg2); returnRun(strFunc,paramArray,pVarResult); } BOOLCCallScript::Run(constCComBSTRstrFunc,constCComBSTRstrArg1,constCComBSTRstrArg2,constCComBSTRstrArg3,CComVariant*pVarResult) { CSimpleArray<CComBSTR>paramArray; paramArray.Add((CComBSTR&)strArg1); paramArray.Add((CComBSTR&)strArg2); paramArray.Add((CComBSTR&)strArg3); returnRun(strFunc,paramArray,pVarResult); } BOOLCCallScript::Run(constCComBSTRstrFunc,constCSimpleArray<CComBSTR>&paramArray,CComVariant*pVarResult) { CComPtr<IDispatch>spScript; if(!GetScript(spScript)) { ShowError("CannotGetScript"); returnFALSE; } CComBSTRbstrMember(strFunc); DISPIDdispid=NULL; HRESULThr=spScript->GetIDsOfNames(IID_NULL,&bstrMember,1, LOCALE_SYSTEM_DEFAULT,&dispid); if(FAILED(hr)) { ShowError(GetSystemErrorMessage(hr)); returnFALSE; } //constintarraySize=paramArray.GetCount(); constintarraySize=paramArray.GetSize(); DISPPARAMSdispparams; memset(&dispparams,0,sizeofdispparams); dispparams.cArgs=arraySize; dispparams.rgvarg=newVARIANT[dispparams.cArgs]; //__asm{int3} CComBSTRbstr; for(inti=0;i<arraySize;i++) { bstr.Empty(); //CComBSTRbstr=paramArray.GetAt(arraySize-1-i);//backreading bstr=paramArray[arraySize-1-i];//backreading //bstr.CopyTo(&dispparams.rgvarg[i].bstrVal);//memoryleak dispparams.rgvarg[i].bstrVal=bstr.m_str;//alsocauseproblemwhenparasaremorethan1 dispparams.rgvarg[i].vt=VT_BSTR; } dispparams.cNamedArgs=0; EXCEPINFOexcepInfo; memset(&excepInfo,0,sizeofexcepInfo); CComVariantvaResult; UINTnArgErr=(UINT)-1;//initializetoinvalidarg hr=spScript->Invoke(dispid,IID_NULL,0, DISPATCH_METHOD,&dispparams,&vaResult,&excepInfo,&nArgErr); ///////////////bugfixmemoryleakcodestart/////////////// //for(intj=0;j<arraySize;j++) //::SysFreeString(dispparams.rgvarg[j].bstrVal); ///////////////bugfixmemoryleakcodeend/////////////// delete[]dispparams.rgvarg; if(FAILED(hr)) { ShowError(GetSystemErrorMessage(hr)); returnFALSE; } if(pVarResult) { *pVarResult=vaResult; } returnFALSE; } 这两个文件的使用的方法: //Getthebrowsercontrol. CAxWindowwnd=GetDlgItem(IDC_EXPLORER);//WebBrowser wnd.QueryControl(&m_spBrowser); CComPtr<IAxWinAmbientDispatch>spAmbient; HRESULThr=wnd.QueryHost(&spAmbient); //diablethecontextmenu //disablethescrollbar if(SUCCEEDED(hr)) { spAmbient->put_AllowContextMenu(VARIANT_TRUE); spAmbient->put_DocHostFlags(docHostUIFlagFLAT_SCROLLBAR); } //navigatetothebasehtml VARIANTflag={0}; VARIANTname={0}; VARIANTpost={0}; VARIANThead={0}; // //m_spBrowser->Navigate(_bstr_t(GetFullName("WhizConsoleSlave.html")),&flag,&name,&post,&head); TCHARszFileName[MAX_PATH]; ::GetModuleFileName(_Module.GetModuleInstance(),szFileName,MAX_PATH); TCHARszRes[MAX_PATH+10]; ::wsprintf(szRes,_T("res://%s/%0d"),szFileName,IDR_HTML); CComVariantvURL(szRes); m_spBrowser->Navigate2(&vURL,&flag,&name,&post,&head);//显示指定的页面 //Createawrapperabouttheexternaldispatchinterface CComObject<CWrapperDispatch>*spdispWrapper=0; hr=CComObject<CWrapperDispatch>::CreateInstance(&spdispWrapper); if(FAILED(hr))return0; //Dummyforrefcountmanagement CComPtr<IUnknown>spUnk=spdispWrapper; //Createtheobjectthatwillhandletheexternalinterfaceforthe //htmlfile. pExternal=newCExternal(m_hWnd); m_oExternal=static_cast<IDispatch*>(pExternal); //Settheexternaldispatchinterface 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的参数.

本文共计1613个文字,预计阅读时间需要7分钟。

如何实现C语言与JavaScript脚本之间的有效互调?

在exe文件中实现脚本和C++的相互调用,可以通过以下步骤进行:

1. 封装脚本接口:首先,需要将脚本的功能封装成一个接口。在脚本中定义一个继承自IDispatch的接口,以便在C++中调用。

2. 创建脚本组件:使用ATL(Active Template Library)或类似工具创建一个脚本组件。在组件中实现封装的接口。

3. 注册COM接口:确保脚本组件的COM接口被正确注册,以便C++代码可以访问。

4. C++调用脚本: - 在C++代码中,使用COM库(如COMDLG32.DLL)创建一个脚本组件的实例。 - 使用IDispatch接口调用脚本中的方法。

如何实现C语言与JavaScript脚本之间的有效互调?

5. 实现脚本与C++的交互: - 在C++中,声明一个指向IDispatch的指针。 - 使用脚本组件的实例初始化这个指针。 - 通过IDispatch指针调用脚本中的方法。

6. 传递参数: - 在调用脚本方法时,可以通过VARIANT类型传递参数。 - 如果需要从脚本传递回C++,同样使用VARIANT类型接收。

7. 示例代码: cpp // C++ 代码示例 #include #include

CoInitialize(); IUnknown* pUnk=NULL; HRESULT hr=CoCreateInstance(CLSID_ScriptComponent, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (LPVOID*)&pUnk); if (SUCCEEDED(hr)) { IDispatch* pDisp=NULL; hr=pUnk->QueryInterface(IID_IDispatch, (LPVOID*)&pDisp); if (SUCCEEDED(hr)) { VARIANT vtResult; vtResult.vt=VT_EMPTY; DISPID dispId=DISPID_PROPERTYGET; hr=pDisp->Invoke(dispId, IID_IDispatch, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &vtResult, NULL, NULL, NULL); if (SUCCEEDED(hr)) { // 处理返回结果 } pDisp->Release(); } pUnk->Release(); } CoUninitialize();

8. 资源管理:确保在C++代码中正确管理COM对象的引用计数,避免内存泄漏。

通过以上步骤,可以在exe文件中实现脚本和C++的相互调用,并传递必要的参数。

脚本调用C++相对比较容易,使用ATL组件只需要抛双接口即可,但在exe里如何做到呢?本文实现了在exe里脚本和C++的相互调用.在EXE里也需要对外抛送一个继承自IDispatch的接口.并需要重载它的所有接口。由于水平有限,所以难免有错。 //头文件 staticconstGUIDIID_CExternal= {0x52fee9af,0xb3b3,0x4756,{0x80,0x10,0xfe,0xa8,0xf9,0xfd,0xd3,0x3f}}; classCExternal:publicIDispatch { public: CExternal(HWNDh); virtual~CExternal(); ULONG__stdcallAddRef(){return1;} ULONG__stdcallRelease(){return1;} HRESULT__stdcallQueryInterface(REFIIDriid,voidFAR*FAR*ppv) { if(ppv==NULL) returnE_POINTER; *ppv=NULL; if(InlineIsEqualGUID(riid,IID_IUnknown)) { *ppv=static_cast<IUnknown*>(this); returnS_OK; } if(InlineIsEqualGUID(riid,IID_IDispatch)) { *ppv=static_cast<IDispatchFAR*>(this); returnS_OK; } if(InlineIsEqualGUID(riid,IID_CExternal)) { *ppv=static_cast<CExternal*>(this); returnS_OK; } returnE_NOINTERFACE; } HRESULT__stdcallGetTypeInfoCount(UINTFAR*pctinfo) { if(pctinfo==NULL) { returnE_INVALIDARG; } //thereisonlyonefunction *pctinfo=1; returnNOERROR; } HRESULT__stdcallGetTypeInfo(UINTiTInfo,LCIDlcid,ITypeInfoFAR*FAR*ppTInfo) { if(ppTInfo==NULL) returnE_INVALIDARG; *ppTInfo=NULL; if(iTInfo!=0) returnDISP_E_BADINDEX; *ppTInfo=m_typeinfo; if(m_typeinfo!=NULL) m_typeinfo->AddRef(); returnNOERROR; } HRESULT__stdcallGetIDsOfNames(REFIIDriid,OLECHARFAR*FAR*rgszNames,unsignedintcNames,LCIDlcid,DISPIDFAR*rgdispid) { if(lstrcmpiW(*rgszNames,L"exec")==0) { *rgdispid=0; returnS_OK; } returnE_FAIL; } HRESULT__stdcallInvoke(DISPIDdispidMember,REFIIDriid,LCIDlcid,WORDwFlags,DISPPARAMSFAR*pdispparams,VARIANTFAR*pvarResult,EXCEPINFOFAR*pexcepinfo,UINTFAR*puArgErr) { if((DISPATCH_PROPERTYGET&wFlags||DISPATCH_METHOD&wFlags) &&dispidMember==0) { CComBSTRsRet; exec(pdispparams,&sRet); if(DISPATCH_PROPERTYGET&wFlags) { pvarResult->vt=VT_BSTR; pvarResult->bstrVal=sRet.Detach(); } returnS_OK; } returnE_FAIL; } HRESULT__stdcallexec(DISPPARAMSFAR*pdispparams,BSTR*pbstrValue); private: HWNDm_hWnd; LPTYPEINFOm_typeinfo; CStringGetVariantStr(VARIANTvVal); }; //实现的文件 CExternal::CExternal(HWNDh) { csDisplayStr=""; m_typeinfo=NULL; m_hWnd=h; //Createanexecfunction staticPARAMDATAPARAM_VALUE[]={{OLESTR("fnName"),VT_BSTR},{OLESTR("p1"),VT_BSTR}}; staticMETHODDATArgmdataCCalc={OLESTR("exec"),PARAM_VALUE,0,0,CC_CDECL,2,DISPATCH_METHOD|DISPATCH_PROPERTYGET,VT_BSTR}; staticINTERFACEDATAifdata={&rgmdataCCalc,1}; HRESULThres=CreateDispTypeInfo(&ifdata,LOCALE_SYSTEM_DEFAULT,&m_typeinfo); } CStringCExternal::GetVariantStr(VARIANTvVal) { CStringcsReVal; switch(vVal.vt) { caseVT_BOOL: { if(vVal.boolVal==VARIANT_TRUE) { return("1"); } else { return("0"); } break; } caseVT_I2: { csReVal.Format("%d",vVal.iVal); return(csReVal); } caseVT_I4: { csReVal.Format("%d",vVal.lVal); return(csReVal); } //caseVT_R8: //{ ////csReVal.Format("%f",vVal.dblVal); //csReVal=vVal.dblVal; //return(csReVal); //} caseVT_BSTR: { return(CString(vVal.bstrVal)); } } return""; } HRESULT__stdcallCExternal::exec(DISPPARAMSFAR*pdispparams,BSTR*pbstrValue)//脚本的入口点 { //noargumentreturn if(pdispparams->cArgs<1) { *pbstrValue=bstrRet.Detach(); returnS_OK; } intargs=pdispparams->cArgs; //Ccallingconventionorderofparametersisinreversed CStringaction=pdispparams->rgvarg[args-1].bstrVal; debugIt("exec***action:%s:%d",action,args); if(action=="alert") { CStringcsMessage; CStringcsTitle; 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); } //elseif(action=="什么") //{ //} *pbstrValue=bstrRet.Detach();//返回值 returnS_OK; } CExternal::~CExternal() { if(m_typeinfo)m_typeinfo->Release(); } C++调用脚本可以使用下面的代码,此代码是我在网上下载的,具体的来源我已经不记得了,但在网上应该可以找到类似的.原理是用到了WebBrowser2,但是C++和脚本的相互调用都用到了HTML页面,使用HTML页面成了包袱,能否丢掉它,我不知道如何实现,望高手指点....... //头文件 #pragmaonce #include<atlbase.h> #include<Mshtml.h> classCCallScript { public: CCallScript(); virtual~CCallScript(); BOOLDocumentSet(){return(m_bDocumentSet);} BOOLSetDocument(IDispatch*pDisp); LPDISPATCHGetHtmlDocument()const; constCComBSTRGetLastError()const; BOOLGetScript(CComPtr<IDispatch>&spDisp); BOOLGetScripts(CComPtr<IHTMLElementCollection>&spColl); BOOLRun(constCComBSTRstrFunc,CComVariant*pVarResult=NULL); BOOLRun(constCComBSTRstrFunc,constCComBSTRstrArg1,CComVariant*pVarResult=NULL); BOOLRun(constCComBSTRstrFunc,constCComBSTRstrArg1,constCComBSTRstrArg2,CComVariant*pVarResult=NULL); BOOLRun(constCComBSTRstrFunc,constCComBSTRstrArg1,constCComBSTRstrArg2,constCComBSTRstrArg3,CComVariant*pVarResult=NULL); BOOLRun(constCComBSTRstrFunc,constCSimpleArray<CComBSTR>&paramArray,CComVariant*pVarResult=NULL); private: BOOLm_bDocumentSet; protected: voidShowError(CComBSTRlpszText); protected: CComPtr<IHTMLDocument2>m_spDoc; CComBSTRm_strError; }; inlinevoidCCallScript::ShowError(CComBSTRlpszText) { m_strError="Error:"; m_strError.Append(lpszText); } inlineconstCComBSTRCCallScript::GetLastError()const { returnm_strError; } inlineLPDISPATCHCCallScript::GetHtmlDocument()const { returnm_spDoc; } //CPP文件 #include"stdafx.h" #include"CallScript.h" #defineCHECK_POINTER(p) ATLASSERT(p!=NULL); if(p==NULL) { ShowError("NULLpointer"); returnFALSE; } constCComBSTRGetSystemErrorMessage(DWORDdwError) { CComBSTRstrError; LPTSTRlpBuffer; if(!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, NULL,dwError, MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT), (LPTSTR)&lpBuffer,0,NULL)) { strError="FormatMessageNetiveError"; } else { strError=lpBuffer; LocalFree(lpBuffer); } returnstrError; } CCallScript::CCallScript() { m_bDocumentSet=FALSE; } CCallScript::~CCallScript() { } BOOLCCallScript::SetDocument(IDispatch*pDisp) { CHECK_POINTER(pDisp); m_spDoc=NULL; CComPtr<IDispatch>spDisp=pDisp; HRESULThr=spDisp->QueryInterface(IID_IHTMLDocument2,(void**)&m_spDoc); if(FAILED(hr)) { ShowError("FailedtogetHTMLdocumentCOMobject"); returnFALSE; } m_bDocumentSet=TRUE; returnTRUE; } BOOLCCallScript::GetScript(CComPtr<IDispatch>&spDisp) { CHECK_POINTER(m_spDoc); HRESULThr=m_spDoc->get_Script(&spDisp); ATLASSERT(SUCCEEDED(hr)); returnSUCCEEDED(hr); } BOOLCCallScript::GetScripts(CComPtr<IHTMLElementCollection>&spColl) { CHECK_POINTER(m_spDoc); HRESULThr=m_spDoc->get_scripts(&spColl); ATLASSERT(SUCCEEDED(hr)); returnSUCCEEDED(hr); } BOOLCCallScript::Run(constCComBSTRstrFunc,CComVariant*pVarResult) { CSimpleArray<CComBSTR>paramArray; returnRun(strFunc,paramArray,pVarResult); } BOOLCCallScript::Run(constCComBSTRstrFunc,constCComBSTRstrArg1,CComVariant*pVarResult) { CSimpleArray<CComBSTR>paramArray; paramArray.Add((CComBSTR&)strArg1); returnRun(strFunc,paramArray,pVarResult); } BOOLCCallScript::Run(constCComBSTRstrFunc,constCComBSTRstrArg1,constCComBSTRstrArg2,CComVariant*pVarResult) { CSimpleArray<CComBSTR>paramArray; paramArray.Add((CComBSTR&)strArg1); paramArray.Add((CComBSTR&)strArg2); returnRun(strFunc,paramArray,pVarResult); } BOOLCCallScript::Run(constCComBSTRstrFunc,constCComBSTRstrArg1,constCComBSTRstrArg2,constCComBSTRstrArg3,CComVariant*pVarResult) { CSimpleArray<CComBSTR>paramArray; paramArray.Add((CComBSTR&)strArg1); paramArray.Add((CComBSTR&)strArg2); paramArray.Add((CComBSTR&)strArg3); returnRun(strFunc,paramArray,pVarResult); } BOOLCCallScript::Run(constCComBSTRstrFunc,constCSimpleArray<CComBSTR>&paramArray,CComVariant*pVarResult) { CComPtr<IDispatch>spScript; if(!GetScript(spScript)) { ShowError("CannotGetScript"); returnFALSE; } CComBSTRbstrMember(strFunc); DISPIDdispid=NULL; HRESULThr=spScript->GetIDsOfNames(IID_NULL,&bstrMember,1, LOCALE_SYSTEM_DEFAULT,&dispid); if(FAILED(hr)) { ShowError(GetSystemErrorMessage(hr)); returnFALSE; } //constintarraySize=paramArray.GetCount(); constintarraySize=paramArray.GetSize(); DISPPARAMSdispparams; memset(&dispparams,0,sizeofdispparams); dispparams.cArgs=arraySize; dispparams.rgvarg=newVARIANT[dispparams.cArgs]; //__asm{int3} CComBSTRbstr; for(inti=0;i<arraySize;i++) { bstr.Empty(); //CComBSTRbstr=paramArray.GetAt(arraySize-1-i);//backreading bstr=paramArray[arraySize-1-i];//backreading //bstr.CopyTo(&dispparams.rgvarg[i].bstrVal);//memoryleak dispparams.rgvarg[i].bstrVal=bstr.m_str;//alsocauseproblemwhenparasaremorethan1 dispparams.rgvarg[i].vt=VT_BSTR; } dispparams.cNamedArgs=0; EXCEPINFOexcepInfo; memset(&excepInfo,0,sizeofexcepInfo); CComVariantvaResult; UINTnArgErr=(UINT)-1;//initializetoinvalidarg hr=spScript->Invoke(dispid,IID_NULL,0, DISPATCH_METHOD,&dispparams,&vaResult,&excepInfo,&nArgErr); ///////////////bugfixmemoryleakcodestart/////////////// //for(intj=0;j<arraySize;j++) //::SysFreeString(dispparams.rgvarg[j].bstrVal); ///////////////bugfixmemoryleakcodeend/////////////// delete[]dispparams.rgvarg; if(FAILED(hr)) { ShowError(GetSystemErrorMessage(hr)); returnFALSE; } if(pVarResult) { *pVarResult=vaResult; } returnFALSE; } 这两个文件的使用的方法: //Getthebrowsercontrol. CAxWindowwnd=GetDlgItem(IDC_EXPLORER);//WebBrowser wnd.QueryControl(&m_spBrowser); CComPtr<IAxWinAmbientDispatch>spAmbient; HRESULThr=wnd.QueryHost(&spAmbient); //diablethecontextmenu //disablethescrollbar if(SUCCEEDED(hr)) { spAmbient->put_AllowContextMenu(VARIANT_TRUE); spAmbient->put_DocHostFlags(docHostUIFlagFLAT_SCROLLBAR); } //navigatetothebasehtml VARIANTflag={0}; VARIANTname={0}; VARIANTpost={0}; VARIANThead={0}; // //m_spBrowser->Navigate(_bstr_t(GetFullName("WhizConsoleSlave.html")),&flag,&name,&post,&head); TCHARszFileName[MAX_PATH]; ::GetModuleFileName(_Module.GetModuleInstance(),szFileName,MAX_PATH); TCHARszRes[MAX_PATH+10]; ::wsprintf(szRes,_T("res://%s/%0d"),szFileName,IDR_HTML); CComVariantvURL(szRes); m_spBrowser->Navigate2(&vURL,&flag,&name,&post,&head);//显示指定的页面 //Createawrapperabouttheexternaldispatchinterface CComObject<CWrapperDispatch>*spdispWrapper=0; hr=CComObject<CWrapperDispatch>::CreateInstance(&spdispWrapper); if(FAILED(hr))return0; //Dummyforrefcountmanagement CComPtr<IUnknown>spUnk=spdispWrapper; //Createtheobjectthatwillhandletheexternalinterfaceforthe //htmlfile. pExternal=newCExternal(m_hWnd); m_oExternal=static_cast<IDispatch*>(pExternal); //Settheexternaldispatchinterface 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的参数.