当前位置 : 主页 > 网络编程 > JavaScript >

SpiderMonkey实现C++和JavaScript的交互

来源:互联网 收集:自由互联 发布时间:2021-06-28
简单执行JS代码 //简单执行JS代码int ExecScript1(JSContext* cx){// Scope for our various stack objects (JSAutoRequest, RootedObject), so they all go// out of scope before we JS_DestroyContext.// In practice, you would want to exit
简单执行JS代码
//简单执行JS代码
int ExecScript1(JSContext* cx)
{
	// Scope for our various stack objects (JSAutoRequest, RootedObject), so they all go
	// out of scope before we JS_DestroyContext.

	// In practice, you would want to exit this any time you're spinning the event loop
	JSAutoRequest ar(cx);

	//在当前的上下文环境,用创建的全局对象创建根化的全局对象
	JS::RootedObject global(cx, JS_NewGlobalObject(cx, &global_class, nullptr, JS::FireOnNewGlobalHook));
	if (!global)
		return 1;

	//创建一个RootedValue变量用于接收执行的结果,而这个结果的值是一个要被根化的值
	JS::RootedValue rval(cx);

	{
		// Scope for JSAutoCompartment
		//进入新全局对象的隔室,好像干什么坏事总是见不得人,非要躲在包厢里做坏事一样
		JSAutoCompartment ac(cx, global);
		//初始化全局对象和其它js里的常规对象
		JS_InitStandardClasses(cx, global);

		const char *script = "'hello'+'world, it is '+new Date()";
		const char *filename = "noname";
		int lineno = 1;
		bool ok = JS_EvaluateScript(cx, global, script, strlen(script), filename, lineno, &rval);
		if (!ok)
			return 1;
	}

	JSString *str = rval.toString();
	printf("%s\n", JS_EncodeString(cx, str));

	return 0;
}
操作JS变量
//操作JS变量
int ExecScript2(JSContext* cx)
{
	// In practice, you would want to exit this any time you're spinning the event loop
	JSAutoRequest ar(cx);

	//在当前的上下文环境,用创建的全局对象创建根化的全局对象
	JS::RootedObject global(cx, JS_NewGlobalObject(cx, &global_class, nullptr, JS::FireOnNewGlobalHook));
	if (!global)
		return 1;

	// Scope for JSAutoCompartment
	//进入新全局对象的隔室,好像干什么坏事总是见不得人,非要躲在包厢里做坏事一样
	JSAutoCompartment ac(cx, global);
	//初始化全局对象和其它js里的常规对象
	JS_InitStandardClasses(cx, global);

	const char* script = "var num=123";
	const char *filename = "noname";
	int lineno = 1;
	//执行脚本
	bool ok = JS_EvaluateScript(cx, global, script, strlen(script), filename, lineno);

	//创建一个RootedValue变量用于接收执行的结果,而这个结果的值是一个要被根化的值
	JS::RootedValue rval(cx);
	//获取js里的变量的值,js里的变量被视为属性
	JS_GetProperty(cx, global, "num", &rval);
	//将js里的整形变量转换为c++里的整形
	int num = JSVAL_TO_INT(rval);
	printf("设置前num=%d\n", num);

	//这里再创建一个根化变量用于设置js里的变量值
	JS::RootedValue setVal(cx);
	setVal.setInt32(99);
	//设置js里变量的值,你换个属性名试试,那就是添加一个属性,当然下面获取也要变为相应的属性名
	JS_SetProperty(cx, global, "num", setVal);
	//再次调用函数获取js变量的值,看是否改变
	JS_GetProperty(cx, global, "num", &rval);
	num = JSVAL_TO_INT(rval);
	printf("设置后num=%d\n", num);

	return 0;
}
主函数
int main(int argc, char* argv[])
{
	//初始化JS引擎,一定要有这步,不然其它的操作都是扯淡
	JS_Init();

	//创建运行时,是不是跟以前的不一样了
	JSRuntime *rt = JS_NewRuntime(8L * 1024 * 1024, JS_USE_HELPER_THREADS);
	if (!rt)
		return 1;

	//创建一个JS上下文,与运行时关联起来
	JSContext *cx = JS_NewContext(rt, 8192);
	if (!cx)
		return 1;

	ExecScript1(cx);
	ExecScript2(cx);
	ExecScript3(cx);
	ExecScript4(cx);
	ExecScript5(cx);
	ExecScript6(cx);

	//销毁创建的上下文
	JS_DestroyContext(cx);
	//销毁释放运行时
	JS_DestroyRuntime(rt);
	//释放js引擎使用的所有资源
	JS_ShutDown();

	return 0;
}
操作JS函数
int add(int a, int b)
{
	return a + b;
}

//这里就是对add函数的包装形式,并且满足JSNative类型
static bool Js_Add(JSContext *cx, unsigned argc, jsval *vp)
{
	JS::CallArgs args = CallArgsFromVp(argc, vp);
	int retValue = add(args[0].toInt32(), args[1].toInt32());
	args.rval().setInt32(retValue);
	return true;
}

//这个函数用于演示如何用spidermonkey引擎来定义js函数
static bool Hello(JSContext *cx, unsigned argc, jsval *vp)
{
	printf("Hello world\n");
	JS::CallArgs args = CallArgsFromVp(argc, vp);

	//设置返回值,这里没有返回值,相当于c++里void的函数,不写也可以的
	args.rval().setNull();
	return true;
}

int ExecScript3(JSContext* cx)
{
	// In practice, you would want to exit this any time you're spinning the event loop
	JSAutoRequest ar(cx);

	//在当前的上下文环境,用创建的全局对象创建根化的全局对象
	JS::RootedObject global(cx, JS_NewGlobalObject(cx, &global_class, nullptr, JS::FireOnNewGlobalHook));
	if (!global)
		return 1;

	// Scope for JSAutoCompartment
	//进入新全局对象的隔室,好像干什么坏事总是见不得人,非要躲在包厢里做坏事一样
	JSAutoCompartment ac(cx, global);
	//初始化全局对象和其它js里的常规对象
	JS_InitStandardClasses(cx, global);

	//下面用于演示如何调用js里的函数
	const char *script = "function add(a,b) {return a+b};";
	const char *filename = "noname";
	int lineno = 1;
	//执行脚本
	bool ret = JS_EvaluateScript(cx, global, script, strlen(script), filename, lineno);

	//用于接收返回值
	JS::RootedValue rval(cx);
	//这是需要传递的参数
	JS::AutoValueArray<2> arry(cx);
	arry[0].setInt32(5);
	arry[1].setInt32(6);
	//通过函数名调用
	JS_CallFunctionName(cx, global, "add", arry, &rval);
	int num = rval.toInt32();
	printf("add函数:num=%d\n", num);

	//这里用于演示如何从js里调用c++里的函数
	JS_DefineFunction(cx, global, "c_add", Js_Add, 2, 0);
	JS::AutoValueArray<2> argv(cx);
	argv[0].setInt32(10);
	argv[1].setInt32(20);
	JS_CallFunctionName(cx, global, "c_add", argv, &rval);
	num = rval.toInt32();
	printf("c_add函数:num=%d\n", num);

	//这里用于演示如何从调用spidermonkey定义的函数
	JSFunction *pFun = JS_DefineFunction(cx, global, "Hello", Hello, 0, 0);//先定义函数
	JS::AutoValueArray<1> argv2(cx);
	argv2[0].setNull();
	JS::RootedFunction rFun(cx, pFun);
	JS_CallFunction(cx, global, rFun, argv2, &rval);//再调用函数,换一种方法调用
	if (rval.isNull())
	{
		printf("Hello函数返回值为null\n");
	}

	return 0;
}
网友评论