很多人比較關注Google的JS V8 JavaScript引擎,確實Google最近很高調。但這個庫在Windows下使用確實有點難度,即使在Linux嵌入,也需要下載gyp,編譯安裝,然后再下載v8,再編譯,再嵌入,再就是……搞這些,你得跳牆,可謂學習成本與應用成本都比較高。
我不迷戀Google,喜歡一些Google的項目,比如angelproject,protobuf。
下一篇文章討論V8與JSRT的性能
下面我來講講Windows Desktop環境嵌入JS腳本支持。在Windows環境,這真是一個寶貝,如果不考慮可移植性,絕對可以很好的替代Lua,因為它比Lua更高效,更易用,支持的開發環境也多。這是一篇中級文章,不詳細介紹到參數如何使用,自己領悟。
微軟為C++提供了非常方便的JS腳本接口(JavaScript Runtime Hosting, JSRT),以至於我了解了這個接口后,認為Lua的基於堆棧式接口實在是非常難用。微軟為JSRT提供了完整的接口文檔,但說明不夠詳盡,也提供了一個風格不太優雅的例子項目,還為C#進行了封裝。微軟也為JSRT提供了調試接口,但本人未使用,所以希望以后的文章有機會再進行講解。
使用JSRT,需要兩樣東西,include <jsrt.h> 連接jsrt.lib,嗯,就是這么簡單的前提。也希望你不要認為后面就很麻煩。
三行代碼即可構建完整的JS運行環境。
JSRT的接口均使用Js前綴,並且返回統一的錯誤代碼,正確運行返回JsNoError。
JS是基於對象的語言,所有函數應該都屬於一個對象,我們注冊到JS環境的函數/變量自然也屬於一個對象——全局對象。
JSRT里的一起對象用C++操作時都是JsRef,可以用JsGetValueType獲取類型。類型有JsString,JsFunction,JsNumber,JsError等。
JSRT當產生異常/錯誤時,可用JsGetAndClearException來獲取並清理,取到的應該是JsError類型。
代碼:
#include <jsrt.h>//別忘了link jsrt.lib
int main()
{
auto r = JsCreateRuntime(JsRuntimeAttributeNone, JsRuntimeVersion11, 0, &runtime);// 創建環境
r = JsCreateContext(runtime, 0, &context);// 創建上下文描述或者叫描述表
r = JsSetCurrentContext(context);// 把上面創建的設置為當前的
// 到這里,環境已經創建完成,可以執行腳本了
JsRef result;
r = JsRunScript(L"var value = 0;", 0, L"", &result);
}
函數支持
JsValueRef CALLBACK jsservice::log(JsValueRef callee, bool isConstructCall,
JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
{
// arguments 參數列表,第一個為調用者
// argumentCount 參數數量
return JS_INVALID_REFERENCE;//如果沒結果
}
// 將函數注冊到JS環境中
// 注冊函數需要一個全局對象作為參數,可以調用JsGetGlobalObject取到
bool reg_func(const wchar_t* name, JsNativeFunction function_pointer)
{
JsPropertyIdRef property_id;
auto ec = JsGetPropertyIdFromName(name, &property_id);
if (ec != JsErrorCode::JsNoError)
return false;
JsValueRef function;
ec = JsCreateFunction(function_pointer, 0, &function);
if (ec != JsErrorCode::JsNoError)
{
JsRelease(propertyId, 0);
return false;
}
ec = JsSetProperty(global_object, property_id, function, true);
if (ec != JsErrorCode::JsNoError)
{
JsRelease(property_id, 0);
JsRelease(function, 0);
return false;
}
return true;
}
注冊到環境以后,就可以在腳本中調用這個函數了。
文章結束
以下是相關引用:
