#define SETERROR(hr) hr
#include
class CScriptHost : public IActiveScriptSite
{
// IActiveScriptSite
STDMETHOD(GetItemInfo)(LPCOLESTR /*pstrName*/, DWORD /*dwReturnMask*/,
IUnknown **ppiunkItem, ITypeInfo **ppti)
{
*ppiunkItem = NULL;
*ppti = NULL;
return S_OK;
}
STDMETHOD(OnScriptError)(IActiveScriptError *pscripterror)
{
return S_OK;
}
STDMETHOD(GetLCID)(LCID *plcid)
{
*plcid = NULL;
return E_NOTIMPL;
}
STDMETHOD(GetDocVersionString)(BSTR* pbstrVersion)
{
*pbstrVersion = NULL;
return E_NOTIMPL;
}
STDMETHOD(OnScriptTerminate)(const VARIANT * /*pvr*/, const EXCEPINFO * /*pei*/)
{
return S_OK;
}
STDMETHOD(OnStateChange)(SCRIPTSTATE /*ssScriptState*/)
{
return S_OK;
}
STDMETHOD(OnEnterScript)()
{
return S_OK;
}
STDMETHOD(OnLeaveScript)()
{
return S_OK;
}
HRESULT Init();
HRESULT Close();
HRESULT AddScriptFile(std::string const& file);
HRESULT GetScriptDispatch(IDispatch** retval);
private:
// Script Engine Wrapper Interfaces
CComPtr
CComPtr
};
#include
#include
#include
using namespace std;
HRESULT CScriptHost::Init(){
CLSID clsJS;
HRESULT hr = ::CLSIDFromProgID(L"javascript", &clsJS);
if (FAILED(hr))
{
return SETERROR(hr);
}
hr = ::CoCreateInstance(clsJS, NULL, CLSCTX_INPROC_SERVER, IID_IActiveScript, (void**)&m_pEngine);
if (FAILED(hr))
{
return SETERROR(hr);
}
hr = m_pEngine.QueryInterface(&m_pEngineParse);
if (FAILED(hr))
{
return SETERROR(hr);
}
hr = m_pEngineParse->InitNew();
if (FAILED(hr))
{
return SETERROR(hr);
}
hr = m_pEngine->SetScriptSite(this);
if (FAILED(hr))
{
return SETERROR(hr);
}
hr = m_pEngine->SetScriptState(SCRIPTSTATE_STARTED);
if (FAILED(hr))
{
return SETERROR(hr);
}
hr = m_pEngine->SetScriptState(SCRIPTSTATE_CONNECTED);
if (FAILED(hr))
{
return SETERROR(hr);
}
return S_OK;
}
HRESULT CScriptHost::Close()
{
HRESULT hr = m_pEngine->SetScriptState(SCRIPTSTATE_DISCONNECTED);
if (FAILED(hr))
{
return SETERROR(hr);
}
hr = m_pEngine->SetScriptState(SCRIPTSTATE_CLOSED);
if (FAILED(hr))
{
return SETERROR(hr);
}
return S_OK;
}
HRESULT CScriptHost::AddScriptFile(string const& file)
{
CAtlFile file;
HRESULT hr = file.Create(file.c_str(), GENERIC_READ, 0, OPEN_EXISTING);
if (FAILED(hr))
{
return SETERROR(hr);
}
ULONGLONG len;
hr = file.GetSize(len);
if (FAILED(hr))
{
return SETERROR(hr);
}
LARGE_INTEGER li;
li.QuadPart = len;
CAutoVectorPtr
if (!szData)
{
return SETERROR(E_OUTOFMEMORY);
}
DWORD dwBytesRead;
hr = file.Read(szData, li.LowPart, dwBytesRead);
if (FAILED(hr))
{
return SETERROR(hr);
}
szData[dwBytesRead] = '\0';
file.Close(); USES_CONVERSION;
wstring script = A2W(szData); EXCEPINFO sEx;
hr = m_pEngineParse->ParseScriptText(script.c_str(), NULL, NULL, NULL,
1, 0, SCRIPTTEXT_ISVISIBLE | SCRIPTTEXT_ISPERSISTENT, NULL, &sEx);
if (FAILED(hr))
{
return SETERROR(hr);
}
return S_OK;
}
HRESULT CScriptHost::GetScriptDispatch(IDispatch** retval)
{
HRESULT hr = m_pEngine->GetScriptDispatch(NULL, retval);
if (FAILED(hr))
{
return SETERROR(hr);
}
return S_OK;
}
使用说明:
假如有一个js文件, c:\test.js, 内容为
function add(x, y)
{
return x + y;
}
c++代码中想去调用js 的add函数并且得到返回值的方法如下:
::CoInitialize(NULL);
CScriptHost host;
host.Init();
host.AddScriptFile("c:\\test.js");
CComPtr
host.GetScriptDispatch(&pJs);
CComVariant var1(10);
CComVariant var2(20);
CComVariant ret;
pJs.Invoke2("add", &var1, &var2, &ret);
host.Close();
::CoUninitialize();