大家好,欢迎来到IT知识分享网。
初次使用SpiderMonkey,对它了解并不多,所以它是什么,请自行去搜索。本文只讲述我们用SpiderMonkey能做什么,我们可以用c/c++调用SpiderMonkey的接口,去执行JavaScript代码。这听起来是不是很酷,现在一起开始吧。
安装
我在linux下,安装很简单,去http://ftp.mozilla.org/pub/mozilla.org/js/下载源码包js-1.7.0.tar.gz,解压后在src/下执行make -f Makefile.ref即可,完成后会生成一个新的目录Linux_All_DBG.OBJ,其中包含静态链接库 libjs.a 和动态链接库 libjs.so 等。
详细请访问基于 C 语言的 JavaScript 引擎探索,本文也是参考此文写的,其中大部分代码来自此文。
SpiderMonkey的api这里不赘述,感兴趣的可以访问 SpiderMonkey官方网站。下面直接附上代码。
代码
.
├── fun.js --JavaScript代码,为求简单,里面只有2个函数
├── lib --Linux_All_DBG.OBJ目录的拷贝,里面的.o文件已被我删除,剩余2个.h文件,libjs.a,libjs.so
├── m --本人比较懒,把gcc命令写到了这个文件,当shell执行
├── src --src目录的拷贝
└── testjs.cc --源代码
fun.js
function add(x, y) {
return x + y;
}
function mul(x, y) {
return x * y;
}
代码简单到不能在简单。
testjs.cc
定义了一个类JSCaller,将js文件加载封装了起来,只调用一次。js中函数可调用多次。
#include <string>
#include "jsapi.h"
/* The class of the global object. */
static JSClass global_class = {
"global",
JSCLASS_GLOBAL_FLAGS,
JS_PropertyStub,
JS_PropertyStub,
JS_PropertyStub,
JS_PropertyStub,
JS_EnumerateStub,
JS_ResolveStub,
JS_ConvertStub,
JS_FinalizeStub,
JSCLASS_NO_OPTIONAL_MEMBERS
};
class JSCaller {
public:
JSCaller();
~JSCaller();
bool Build(const std::string& file);
void Run();
private:
JSBool EvalScriptFromFile(JSContext *context, const char *file);
JSRuntime *runtime_;
JSContext *context_;
JSObject *global_;
};
int main() {
JSCaller caller;
if (!caller.Build("fun.js")) { // 加载js文件,只调用一次
return -1;
}
caller.Run(); // 执行js中的函数,里面执行了多次函数
return 0;
}
JSCaller::JSCaller() {
runtime_ = NULL;
context_ = NULL;
global_ = NULL;
}
JSCaller::~JSCaller() {
if (context_ != NULL) {
JS_DestroyContext(context_);
}
if (runtime_ != NULL) {
JS_DestroyRuntime(runtime_);
}
JS_ShutDown();
}
/* The error reporter callback. */
void ReportError(JSContext *cx, const char *message, JSErrorReport *report) {
if (report->filename == NULL) {
fprintf(stderr, "%s\n", message);
} else {
fprintf(stderr, "%s:%d:%s\n", report->filename, report->lineno, message);
}
}
bool JSCaller::Build(const std::string& file) {
runtime_ = JS_NewRuntime(8L * 1024L * 1024L);
if (runtime_ == NULL) {
return false;
}
context_ = JS_NewContext(runtime_, 512 * 1024);
if (context_ == NULL) {
return false;
}
JS_SetOptions(context_, JSOPTION_VAROBJFIX);
JS_SetErrorReporter(context_, ReportError);
global_ = JS_NewObject(context_, &global_class, NULL, NULL);
if (global_ == NULL) {
return false;
}
if (!JS_InitStandardClasses(context_, global_)) {
return false;
}
JSBool status = EvalScriptFromFile(context_, file.c_str());
if (status == JS_FALSE){
fprintf(stderr, "error while evaluate the script\n");
return false;
}
return true;
}
JSBool JSCaller::EvalScriptFromFile(JSContext *context, const char *file) {
JSScript *script;
// JSString *jss;
JSBool status;
jsval value;
//get the global object
JSObject *global = JS_GetGlobalObject(context);
//compile the script for further using
script = JS_CompileFile(context, global, file);
if (script == NULL) {
return JS_FALSE;
}
//execute it once
status = JS_ExecuteScript(context, global, script, &value);
/*
jss = JS_ValueToString(context, value);
printf("eval script result is : %s\n", JS_GetStringBytes(jss));
*/
//destory the script object
JS_DestroyScript(context, script);
return status;
}
void JSCaller::Run() {
// 调用1000次add和mul函数
for (int i = 0; i < 1000; ++i) {
jsval res;
JSObject *global = JS_GetGlobalObject(context_);
jsval argv[2];
// 构造函数的参数
JS_NewNumberValue(context_, i, &res);
argv[0] = res;
JS_NewNumberValue(context_, i+10, &res);
argv[1] = res;
const char *p = "add";
if (i % 2 == 0) {
p = "mul";
}
// 调用函数
JS_CallFunctionName(context_, global, p, 2, argv, &res);
//convert the result to jsdouble
jsdouble d;
JS_ValueToNumber(context_, res, &d);
printf("%s result = %f\n", p, d);
}
}
编译命令
g++ -I./lib -I./src -DXP_UNIX -L./lib -ljs -g -Wall -o jstest testjs.cc
-I./lib,是因为lib/中也有2个.h文件,不然找不到会报很多错。
本打算使用静态库编译,使用-Wl,-Bstatic -ljs -Wl,-Bdynamic后总是报错,最后放弃了。
所以编译出的二进制执行前,别忘了export LD_LIBRARY_PATH=lib/。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/24172.html