咱們知道實現C++和Javascript通信有下表5種接口:ide
引擎 | 編寫語言 | API接口 | C、C++與JavaScript交互(變量、函數、類) | vc2005編譯靜態庫的大小 | 示例EXE的大小 | 執行、解析JavaScript的速度 |
Google V8 | C++ | C++ | 能夠 | 23.1M | 1.1M | 最快 |
Firefox3.5之前 SpiderMonkey | C | C | 能夠 | 1.3M | 500K | 慢 |
Firefox高版本SpiderMonkey | C++ | C | 能夠 | 15.3M | 1.7M | 通常 |
Webkit JavaScriptCore | C++ | C | 能夠 | 26.2M | 1.4M | 通常 |
IE | 未知 | COM | 能夠 | 未知 | 100K(沒有連接庫) | 通常 |
IE的Trident引擎是非開源的,微軟JavaScript引擎也是非開源的。微軟對外提供了一組COM接口。使用這組COM接口,可以將微軟的JavaScript、VBScript嵌入到C、C++、VB、C#等宿主語言中。函數
說到底其實也沒什麼好說的,先定義一個 CComPtr<IDispatch> 對象,而後調用其對象的Invoke函數,只要弄清楚他的參數正確的傳遞就行了。this
除此以外該接口還提供有一種簡易的方法。spa
CComPtr<IDispatch> Obj; CComVariant var(true); if( FAILED(Obj.Invoke1(L"ReflowDocument", &var)) ) MessageBox(_T("Invoke ReflowDocument failed."));
另外還有Invoke0、Invoke二、InvokeN、GetProperty、PutProperty、GetIDOfName、GetPropertyByName。這些函數的實現都在\VC\atlmfc\include\atlcomcli.h頭文件中有聲明和實現。code
//specialization for IDispatch template <> class CComPtr<IDispatch> : public CComPtrBase<IDispatch> { public: CComPtr() throw() { } CComPtr(_Inout_opt_ IDispatch* lp) throw() : CComPtrBase<IDispatch>(lp) { } CComPtr(_Inout_ const CComPtr<IDispatch>& lp) throw() : CComPtrBase<IDispatch>(lp.p) { } IDispatch* operator=(_Inout_opt_ IDispatch* lp) throw() { if(*this!=lp) { return static_cast<IDispatch*>(AtlComPtrAssign((IUnknown**)&p, lp)); } return *this; } IDispatch* operator=(_Inout_ const CComPtr<IDispatch>& lp) throw() { if(*this!=lp) { return static_cast<IDispatch*>(AtlComPtrAssign((IUnknown**)&p, lp.p)); } return *this; } CComPtr(_Inout_ CComPtr<IDispatch>&& lp) throw() : CComPtrBase<IDispatch>() { p = lp.p; lp.p = NULL; } IDispatch* operator=(_Inout_ CComPtr<IDispatch>&& lp) throw() { if (*this != lp) { if (p != NULL) p->Release(); p = lp.p; lp.p = NULL; } return *this; } // IDispatch specific stuff _Check_return_ HRESULT GetPropertyByName( _In_z_ LPCOLESTR lpsz, _Out_ VARIANT* pVar) throw() { ATLASSERT(p); ATLASSERT(pVar); DISPID dwDispID; HRESULT hr = GetIDOfName(lpsz, &dwDispID); if (SUCCEEDED(hr)) hr = GetProperty(dwDispID, pVar); return hr; } _Check_return_ HRESULT GetProperty( _In_ DISPID dwDispID, _Out_ VARIANT* pVar) throw() { return GetProperty(p, dwDispID, pVar); } _Check_return_ HRESULT PutPropertyByName( _In_z_ LPCOLESTR lpsz, _In_ VARIANT* pVar) throw() { ATLASSERT(p); ATLASSERT(pVar); DISPID dwDispID; HRESULT hr = GetIDOfName(lpsz, &dwDispID); if (SUCCEEDED(hr)) hr = PutProperty(dwDispID, pVar); return hr; } _Check_return_ HRESULT PutProperty( _In_ DISPID dwDispID, _In_ VARIANT* pVar) throw() { return PutProperty(p, dwDispID, pVar); } _Check_return_ HRESULT GetIDOfName( _In_z_ LPCOLESTR lpsz, _Out_ DISPID* pdispid) throw() { return p->GetIDsOfNames(IID_NULL, const_cast<LPOLESTR*>(&lpsz), 1, LOCALE_USER_DEFAULT, pdispid); } // Invoke a method by DISPID with no parameters _Check_return_ HRESULT Invoke0( _In_ DISPID dispid, _Out_opt_ VARIANT* pvarRet = NULL) throw() { DISPPARAMS dispparams = { NULL, NULL, 0, 0}; return p->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, pvarRet, NULL, NULL); } // Invoke a method by name with no parameters _Check_return_ HRESULT Invoke0( _In_z_ LPCOLESTR lpszName, _Out_opt_ VARIANT* pvarRet = NULL) throw() { HRESULT hr; DISPID dispid; hr = GetIDOfName(lpszName, &dispid); if (SUCCEEDED(hr)) hr = Invoke0(dispid, pvarRet); return hr; } // Invoke a method by DISPID with a single parameter _Check_return_ HRESULT Invoke1( _In_ DISPID dispid, _In_ VARIANT* pvarParam1, _Out_opt_ VARIANT* pvarRet = NULL) throw() { DISPPARAMS dispparams = { pvarParam1, NULL, 1, 0}; return p->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, pvarRet, NULL, NULL); } // Invoke a method by name with a single parameter _Check_return_ HRESULT Invoke1( _In_z_ LPCOLESTR lpszName, _In_ VARIANT* pvarParam1, _Out_opt_ VARIANT* pvarRet = NULL) throw() { DISPID dispid; HRESULT hr = GetIDOfName(lpszName, &dispid); if (SUCCEEDED(hr)) hr = Invoke1(dispid, pvarParam1, pvarRet); return hr; } // Invoke a method by DISPID with two parameters _Check_return_ HRESULT Invoke2( _In_ DISPID dispid, _In_ VARIANT* pvarParam1, _In_ VARIANT* pvarParam2, _Out_opt_ VARIANT* pvarRet = NULL) throw(); // Invoke a method by name with two parameters _Check_return_ HRESULT Invoke2( _In_z_ LPCOLESTR lpszName, _In_ VARIANT* pvarParam1, _In_ VARIANT* pvarParam2, _Out_opt_ VARIANT* pvarRet = NULL) throw() { DISPID dispid; HRESULT hr = GetIDOfName(lpszName, &dispid); if (SUCCEEDED(hr)) hr = Invoke2(dispid, pvarParam1, pvarParam2, pvarRet); return hr; } // Invoke a method by DISPID with N parameters _Check_return_ HRESULT InvokeN( _In_ DISPID dispid, _In_ VARIANT* pvarParams, _In_ int nParams, _Out_opt_ VARIANT* pvarRet = NULL) throw() { DISPPARAMS dispparams = { pvarParams, NULL, nParams, 0}; return p->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, pvarRet, NULL, NULL); } // Invoke a method by name with Nparameters _Check_return_ HRESULT InvokeN( _In_z_ LPCOLESTR lpszName, _In_ VARIANT* pvarParams, _In_ int nParams, _Out_opt_ VARIANT* pvarRet = NULL) throw() { HRESULT hr; DISPID dispid; hr = GetIDOfName(lpszName, &dispid); if (SUCCEEDED(hr)) hr = InvokeN(dispid, pvarParams, nParams, pvarRet); return hr; } _Check_return_ static HRESULT PutProperty( _In_ IDispatch* p, _In_ DISPID dwDispID, _In_ VARIANT* pVar) throw() { ATLASSERT(p); ATLASSERT(pVar != NULL); if (pVar == NULL) return E_POINTER; if(p == NULL) return E_INVALIDARG; ATLTRACE(atlTraceCOM, 2, _T("CPropertyHelper::PutProperty\n")); DISPPARAMS dispparams = {NULL, NULL, 1, 1}; dispparams.rgvarg = pVar; DISPID dispidPut = DISPID_PROPERTYPUT; dispparams.rgdispidNamedArgs = &dispidPut; if (pVar->vt == VT_UNKNOWN || pVar->vt == VT_DISPATCH || (pVar->vt & VT_ARRAY) || (pVar->vt & VT_BYREF)) { HRESULT hr = p->Invoke(dwDispID, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUTREF, &dispparams, NULL, NULL, NULL); if (SUCCEEDED(hr)) return hr; } return p->Invoke(dwDispID, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL); } _Check_return_ static HRESULT GetProperty( _In_ IDispatch* p, _In_ DISPID dwDispID, _Out_ VARIANT* pVar) throw() { ATLASSERT(p); ATLASSERT(pVar != NULL); if (pVar == NULL) return E_POINTER; if(p == NULL) return E_INVALIDARG; ATLTRACE(atlTraceCOM, 2, _T("CPropertyHelper::GetProperty\n")); DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0}; return p->Invoke(dwDispID, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &dispparamsNoArgs, pVar, NULL, NULL); } };
上面這些其實也都是調用了Invoke函數,固然你若是不想用它幫你封裝過的這些函數的話,你能夠自行調用比上面這些更原始的Invoke,或者從新封裝一下它。對象
總而言之,當你作這就事的時候必定要不停的查閱MSDN,沒了它你就是在蒙着眼睛摸象加自欺欺人。blog