上一篇文章把SpiderMonkey引擎简单的封装了一下,实现了JsEngine类。但是JsEngine并没有给SpiderMonkey添加任何扩展,所以能力相当有限,甚至连个alert()函数也没有这一篇就来看一看,如何扩展SpiderMonkey引擎,把自定义的C++ alert()函数暴露给JS。
#include "JsEngine.h" class JsEngine2 : public JsEngine { public: JsEngine2(); virtual ~JsEngine2(); };
static void alert(std::string msg) { std::cout << msg << "\n"; }这个alert()函数如此平淡无奇,所以也无需过多的解释,接着看如何让JS代码可以使用这个函数。
typedef JSBool (*JSNative)(JSContext *cx, unsigned argc, JS::Value *vp);好吧,兜了半天的圈子,请出JSNative版alert:
static JSBool myjs_alert(JSContext *cx, unsigned argc, jsval *vp) { JSString *str; if (!JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "S", &str)) return JS_FALSE; char *msg = JS_EncodeString(cx, str); alert(msg); JS_free(cx, msg); JS_SET_RVAL(cx, vp, JSVAL_VOID); return JS_TRUE; }
static JSFunctionSpec myjs_global_functions[] = { JS_FS("alert", myjs_alert, 1, 0), JS_FS_END }; JsEngine2::JsEngine2() { if (!JS_DefineFunctions(cx, global, myjs_global_functions)) { return; } }
#include <iostream> #include "JsEngine2.h" static void alert(std::string msg) { std::cout << msg << "\n"; } static JSBool myjs_alert(JSContext *cx, unsigned argc, jsval *vp) { JSString *str; if (!JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "S", &str)) return JS_FALSE; char *msg = JS_EncodeString(cx, str); alert(msg); JS_free(cx, msg); JS_SET_RVAL(cx, vp, JSVAL_VOID); return JS_TRUE; } static JSFunctionSpec myjs_global_functions[] = { JS_FS("alert", myjs_alert, 1, 0), JS_FS_END }; JsEngine2::JsEngine2() { if (!JS_DefineFunctions(cx, global, myjs_global_functions)) { return; } } JsEngine2::~JsEngine2() { }
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. JsEngine2 engine; engine.execJS("alert('Hello World!');"); }启动虚拟机: