大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。
Jetbrains全系列IDE稳定放心使用
关键词: SpiderMonkey
一下将逐步记录我学习的过程。
在
http://ftp.mozilla.org/pub/mozilla.org/js/ 下面有一个文件js-1.60.tar.gz, 这个就是SpiderMonkey的源代码
将源码下载后,解压缩。比如我下载到 /home/xufeng/work/jsEngine 下面,解压后就产生一个文件夹js,源文件全部在js/src中,进入js/src,进行编译(请参考README)。
以上所用的命令有:
$tar xvzf js-1.60.tar.gz
$cd js/src
$make -f Makefile.ref
编译过后就会生成javascript引擎的静态库和动态库,分别是libjs.a和libjs.so,在js/src/Linux_All_DBG.OBJ/目录下面.进入这个目录就可以看见.如果要使用javascript引擎,只要在头文件中包含jsapi.h 同时在编译的时候链接这些库就可以了.
在Linux_ALL_DBG.OBJ目录下面还有一个可执行程序 js, 运行这个程序将产生类似shell的东西,可以在下面运行javascript代码.
先写一个最简单的程序,用来执行一段javascript代码(javascript代码也是很简单).这个程序也基本上展示了最主要的几个API.
程序如下:
/**
*程序 test1.c
*执行一段javascript代码
*/
#include “jsapi.h”
/* EXIT_FAILURE and EXIT_SUCCESS */
#include “stdlib.h”
/* strlen */
#include “string.h”
{
/* pointer to our runtime object */
if(argc!=2){
usage();
exit(-1);
}
JSRuntime *runtime = NULL;
/* pointer to our context */
JSContext *context = NULL;
/* pointer to our global JavaScript object */
JSObject *global = NULL;
const char *script = argv[1];
/* JavaScript value to store the result of the script */
jsval rval;
if ((!(runtime = JS_NewRuntime(1024L * 1024L)))
|| (!(context = JS_NewContext(runtime, 8192)))
|| (!(global = JS_NewObject(context, NULL, NULL, NULL)))
)
return EXIT_FAILURE;
/* set global object of context and initialize standard ECMAScript
* objects (Math, Date, …) within this global object scope */
if (!JS_InitStandardClasses(context, global))
return EXIT_FAILURE;
if (!JS_EvaluateScript(context, global, script, strlen(script), “script”, 1, &rval))
return EXIT_FAILURE;
JS_DestroyContext(context);
JS_DestroyRuntime(runtime);
JS_ShutDown();
return EXIT_SUCCESS;
}
{
printf(“example1 script_content/n”);
printf(“for example:./example1 /”var a=1;b=2;a+b/”/n”);
}
/**
*程序结束
*/
以上程序写好以后就要编译了,编译的时候要注意增加一些编译参数。这里我写了一个简单的Makefile
########################################################################################################
ROSS_COMPILE_PREFIX =
CROSS_COMPILE_PATH =
CC = $(CROSS_COMPILE_PREFIX)gcc
CFLAGS = -DXP_UNIX -DJS_THREADSAFE -g -O0 -Wall -W -pedantic -std=c99 -I$(HOME)/work/jsEngine/js/src/
LDFLAGS = -L$(HOME)/work/jsEngine/js/src/Linux_All_DBG.OBJ/
LIBS = -ljs
DFLAGS = -g -DDEBUG
CLINK = -c -o
RM = rm -f
CFILES = test1.c
EXECUTABLE = $(patsubst %.c,%, $(CFILES))
DEPENDENCY = $(patsubst %.c,%.d, $(CFILES))
find -name ‘*.[ch]’|xargs indent -kr -cli4 -i4 -nut
doc:
doxygen
include $(DEPENDENCY)
%: %.o
$(CC) $< $(LIBS) -o $@ $(LDFLAGS)
%.o: %.c
$(CC) -c $< -o$@ $(CFLAGS)
%.d: %.c
$(CC) -MM $(CFLAGS) $< >$@.$$$$;/
sed ‘s,/($*/)/.o:,/1.o
$@:,g’ <
$@.$$$$ >
$@;/
$(RM)
$@.$$$$;
clean:
$(RM) $(EXECUTABLE) *.o *.bak *.c~ *.h~ *.d
########################################################################################################
-ljs — 链接的时候增加libjs.so库
-DXP_UNIX — 告诉编译器define XP_UNIX,使得javascript引擎知道操作系统是Unix或类似于Unix系统(这个参数是必需的,否则编译出错,我就在这里碰了跟头)
-O0 — 不让编译器进行优化
1. 创建一个Runtime, API为 JS_NewRuntime()
2. 创建一个Context, API为 JS_NewContext()
3. 创建一个对象Object, API为 JS_NewObject()
4. 初始化全局对象 JS_InitStandardClasses()
5. 执行javascript代码 JS_EvaluateScript()
6. 销毁上下文Context JS_DestroyContext()
7. 销毁Runtime JS_DestroyRuntime()
以上就是主要的过程, 接下来的一些深入的工作都是基于此的.
在上面的程序中,javascript语句是当作命令行参数传给程序的, 有点的时候觉得不太方便, 于是将所有的javascript写道一个文件中, 然后解析这个文件, 执行语句. 执行一个文件中的javascript语句一般有两种方法:其一是定义FILE *fp, 利用 fp 将这个文件所有字节读出来,然后作为字符串传递给JS_EvaluateScript() API,得到结果;第二种是先编译这个js文件,然后再执行已经编译的文件。以下将给出这两种方法的实例。
/**
*程序 test2.c
*利用FILE *fp文件指针执行js文件的代码
*/
#include “jsapi.h”
{
“global”,
0,
JS_PropertyStub,
JS_PropertyStub,
JS_PropertyStub,
JS_PropertyStub,
JS_EnumerateStub,
JS_ResolveStub,
JS_ConvertStub,
JS_FinalizeStub,
JSCLASS_NO_OPTIONAL_MEMBERS
};
int main()
{
JSString* jss;
char buf[5120];
int len;
jsval rval;
JSRuntime *rt;
JSContext *cx;
JSObject *globalObj;
rt = JS_NewRuntime(1024L*1024L);
if (!rt)return -1;
cx = JS_NewContext(rt, 8L*1024L);
if (!cx)return -1;
if (!(globalObj = JS_NewObject (cx, &global_class, NULL, NULL)))return -1;
JS_InitStandardClasses (cx, globalObj);
FILE* fp;
if (!(fp = fopen (“test.js”, “r”)))return -1;
len = fread (buf, 1, 5120, fp);
fclose (fp);
if (len <= 0)return -1;
JS_EvaluateScript (cx, globalObj, buf, len, “”, 1, &rval);
jss = JS_ValueToString (cx, rval);
fprintf(stdout, “The result is: %s/n”, JS_GetStringBytes(jss));
JS_DestroyContext(cx);
JS_DestroyRuntime(rt);
return 0;
}
*程序结束
*/
javascript文件内容如下:
/**
*test.js
*/
var i = 1;
var j = 2;
i+j;
/**
*End
*/
The result is: 3
/**
*程序 test3.c
*先编译js文件,再执行文件
*/
/* EXIT_FAILURE and EXIT_SUCCESS */
#include “stdlib.h”
/* strlen */
#include “string.h”
/* get SpiderMonkey API declarations */
#include “sys/types.h”
#include “sys/stat.h”
#include “jsapi.h”
JSBool JsFileExecute(JSContext *ctx, const char *file);
int usage(const char *progname);
“System”,
0,
JS_PropertyStub,
JS_PropertyStub,
JS_PropertyStub,
JS_PropertyStub,
JS_EnumerateStub,
JS_ResolveStub,
JS_ConvertStub,
JS_FinalizeStub,
JSCLASS_NO_OPTIONAL_MEMBERS
};
{
JSRuntime *rt = NULL;
JSContext *ctx = NULL;
JSObject *obj = NULL;
char *file = NULL;
if (argc < 2)
{
usage(argv[0]);
}
else
{
file = argv[1];
}
rt = JS_NewRuntime(1024L*1024L);
if(!rt)
{
printf(“Runtime created failed./n”);
return -1;
}
ctx = JS_NewContext(rt, 8L*1024L);
if(!ctx)
{
printf(“Context created failed./n”);
JS_DestroyRuntime(rt);
return -1;
}
obj = JS_NewObject(ctx, &JsGlobalObjectClass, NULL, NULL);
if(!obj)
{
printf(“Object created failed./n”);
JS_DestroyContext(ctx);
JS_DestroyRuntime(rt);
return -1;
}
JS_InitStandardClasses(ctx, obj);
{
printf(“File execute successfully./n”);
}
else
{
printf(“File execute failed./n”);
}
return 0;
}
{
printf(“Usage: %s <file>/n”, progname);
exit(-1);
}
{
JSScript *script = NULL;
JSString *jss;
JSBool retval;
jsval ret;
JSObject *global = JS_GetGlobalObject(ctx);
script = JS_CompileFile(ctx, global, file);
if(script == NULL)
{
return JS_FALSE;
}
retval = JS_ExecuteScript(ctx, global, script, &ret);
jss = JS_ValueToString (ctx, ret);
printf(“The result is: %s/n”, JS_GetStringBytes(jss));
JS_DestroyScript(ctx, script);
return retval;
}
/**
*End
*/
这种方法先是用JS_CompileFile() API来编译文件,得到一个script,然后再JS_ExecuteScript() 来运行script,我觉得这种方法更加好一些。
运行的时候,js文件还是用的test.js,其源码同上。
javascript是面向对象的,一个类常有构造函数、属性和方法等,在下面的程序中我们构建一个类,并逐步增加类的属性和方法。
在如下程序中,定义了一个PeopleClass类,然后用
static JSFunctionSpec PeopleMethods[] = {
{“print”, PeoplePrint, 0, 0, 0},
{NULL}
};
来定义类的方法,如果有更多的方法也可以在这里定义,其中 “print” 是将在javascript中采用的方法名,PeoplePrint是在程序中实现的类的方法,后面的参数请参考API说明。
/**
*程序 test4.c
*/
#include “jsapi.h”
JSBool JsFileExecute(JSContext *ctx, const char *file);
int usage(const char *progname);
{
char name[16];
char addr[64];
char tel[10];
}PeopleInfo;
static PeopleInfo pinfo={“xufeng”, “Chongqing”, “123456”};
“global”,
0,
JS_PropertyStub,
JS_PropertyStub,
JS_PropertyStub,
JS_PropertyStub,
JS_EnumerateStub,
JS_ResolveStub,
JS_ConvertStub,
JS_FinalizeStub,
JSCLASS_NO_OPTIONAL_MEMBERS
};
“people”,
0,
JS_PropertyStub,
JS_PropertyStub,
JS_PropertyStub,
JS_PropertyStub,
JS_EnumerateStub,
JS_ResolveStub,
JS_ConvertStub,
JS_FinalizeStub,
JSCLASS_NO_OPTIONAL_MEMBERS
};
{“print”, PeoplePrint, 0, 0, 0},
{NULL}
};
int main(int argc, char **argv)
{
JSRuntime *rt;
JSContext *cx;
JSObject *globalObj,*PeopleObj;
char *file = NULL;
if (argc < 2)
{
usage(argv[0]);
}
else
{
file = argv[1];
}
rt = JS_NewRuntime(1024L*1024L);
if (!rt)return -1;
cx = JS_NewContext(rt, 8L*1024L);
if (!cx)return -1;
if (!(globalObj = JS_NewObject (cx, &global_class, NULL, NULL)))return -1;
JS_InitStandardClasses (cx, globalObj);
PeopleObj = JS_DefineObject (cx, globalObj, “people”, &PeopleClass, 0, JSPROP_ENUMERATE);
JS_DefineFunctions (cx,PeopleObj, PeopleMethods);
if(JsFileExecute(cx, file))
{
printf(“File execute successfully./n”);
}
else
{
printf(“File execute failed./n”);
}
JS_DestroyContext(cx);
JS_DestroyRuntime(rt);
return 0;
}
{
fprintf(stdout,”My Name is %s./nMy Addr is %s./nMy telephone is %s/n”, pinfo.name, pinfo.addr, pinfo.tel);
return JS_TRUE;
}
JSBool JsFileExecute(JSContext *ctx, const char *file)
{
JSScript *script = NULL;
JSBool retval;
jsval ret;
JSObject *global = JS_GetGlobalObject(ctx);
script = JS_CompileFile(ctx, global, file);
if(script == NULL)
{
return JS_FALSE;
}
retval = JS_ExecuteScript(ctx, global, script, &ret);
JS_DestroyScript(ctx, script);
return retval;
}
int usage(const char *progname)
{
printf(“Usage: %s <file>/n”, progname);
exit(-1);
}
/**
*End
*/
运行的时候,在javascript中增加对象的使用,修改后的test.js内容如下:
/**
*javascript start
*/
people.print();
/**
*END
*/
编译后运行:./test4 test.js
程序将会产生如下结果:
My Name is xufeng.
My Addr is Chongqing.
My telephone is 123456
File execute successfully.
程序如下:
/**
*程序 test5.c
*增加对象的属性
*增加错误报警函数
*/
#include “stdio.h”
#include “stdlib.h”
#include “jsapi.h”
#include “sys/types.h”
#include “sys/stat.h”
static JSBool GetPeopleProperty (JSContext *cx, JSObject *obj, jsval id, jsval *vp);
static JSBool SetPeopleProperty (JSContext *cx, JSObject *obj, jsval id, jsval *vp);
static JSBool PeoplePrint(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
static void JsErrorHandler(JSContext *ctx, const char *msg, JSErrorReport *er);
int usage(const char *progname);
JSBool JsFileExecute(JSContext *ctx, const char *file);
{
char name[16];
char addr[64];
char tel[10];
}PeopleInfo;
static PeopleInfo pinfo={“xufeng”, “Chongqing”, “123456”};
“global”,
0,
JS_PropertyStub,
JS_PropertyStub,
JS_PropertyStub,
JS_PropertyStub,
JS_EnumerateStub,
JS_ResolveStub,
JS_ConvertStub,
JS_FinalizeStub,
JSCLASS_NO_OPTIONAL_MEMBERS
};
“people”,
0,
JS_PropertyStub,
JS_PropertyStub,
GetPeopleProperty,
SetPeopleProperty,
JS_EnumerateStub,
JS_ResolveStub,
JS_ConvertStub,
JS_FinalizeStub,
JSCLASS_NO_OPTIONAL_MEMBERS
};
{“name”, NAME, JSPROP_ENUMERATE},
{“address”, ADDRESS, JSPROP_ENUMERATE},
{“tel”, TEL, JSPROP_ENUMERATE},
{NULL}
};
static JSFunctionSpec PeopleMethods[] = {
{“print”, PeoplePrint, 0, 0, 0},
{NULL}
};
int main(int argc, char **argv)
{
JSRuntime *rt;
JSContext *cx;
JSObject *globalObj,*PeopleObj;
char *file = NULL;
if (argc < 2)
{
usage(argv[0]);
}
else
{
file = argv[1];
}
rt = JS_NewRuntime(1024L*1024L);
if (!rt)return -1;
cx = JS_NewContext(rt, 8L*1024L);
if (!cx)return -1;
JS_SetErrorReporter(cx, JsErrorHandler);
if (!(globalObj = JS_NewObject (cx, &global_class, NULL, NULL)))return -1;
JS_InitStandardClasses (cx, globalObj);
PeopleObj = JS_DefineObject (cx, globalObj, “people”, &PeopleClass, 0, JSPROP_ENUMERATE);
JS_DefineProperties (cx,PeopleObj, PeopleProperties);
JS_DefineFunctions (cx,PeopleObj, PeopleMethods);
if(JsFileExecute(cx, file))
{
printf(“File execute successfully./n”);
}
else
{
printf(“File execute failed./n”);
}
JS_DestroyContext(cx);
JS_DestroyRuntime(rt);
return 0;
}
{
printf(“JS Error: %s/nFile: %s:%u/n”, msg, er->filename, er->lineno);
}
{
if (JSVAL_IS_INT(id)) {
switch (JSVAL_TO_INT(id)) {
case NAME:
*vp=STRING_TO_JSVAL (JS_NewStringCopyZ (cx,pinfo.name));
break;
case ADDRESS:
*vp=STRING_TO_JSVAL (JS_NewStringCopyZ (cx,pinfo.addr));
break;
case TEL:
*vp=STRING_TO_JSVAL (JS_NewStringCopyZ (cx,pinfo.tel));
break;
}
}
return JS_TRUE;
}
{
if (JSVAL_IS_INT(id)) {
switch (JSVAL_TO_INT(id)) {
case NAME:
strncpy(pinfo.name, JS_GetStringBytes(JS_ValueToString(cx, *vp)), 15);
break;
case ADDRESS:
strncpy(pinfo.addr, JS_GetStringBytes(JS_ValueToString(cx, *vp)), 63);
break;
case TEL:
strncpy(pinfo.tel, JS_GetStringBytes(JS_ValueToString(cx, *vp)), 9);
break;
}
}
return JS_TRUE;
}
{
fprintf(stdout,”My Name is %s./nMy Addr is %s./nMy telephone is %s/n”, pinfo.name, pinfo.addr, pinfo.tel);
return JS_TRUE;
}
{
printf(“Usage: %s <file>/n”, progname);
exit(-1);
}
JSBool JsFileExecute(JSContext *ctx, const char *file)
{
JSScript *script = NULL;
JSBool retval;
jsval ret;
JSObject *global = JS_GetGlobalObject(ctx);
script = JS_CompileFile(ctx, global, file);
if(script == NULL)
{
return JS_FALSE;
}
retval = JS_ExecuteScript(ctx, global, script, &ret);
JS_DestroyScript(ctx, script);
return retval;
}
/**
*END
*/
接下来修改test.js,修改后如下:
/**
*javascript start
*/
people.print();
people.name = “John”;
people.address = “Beijing”;
people.tel = “00099988”;
people.print();
/**
*END
*/
编译运行 ./test5 test.js 得到如下结果:
My Name is xufeng.
My Addr is Chongqing.
My telephone is 123456
My Name is John.
My Addr is Beijing.
My telephone is 00099988
File execute successfully.
JS_ValueToNumber, JS_ValueToInt32, JS_ValueToECMAInt32, JS_ValueToECMAUint32,
JS_ValueToBoolean, JS_ValueToUint16, JS_ValueToString, JS_ValueToObject,
JS_ValueToFunction
JS_NewNumberValue, JS_NewJS_NewStringCopyZ, JS_UCStringCopyZ, JS_NewArrayObject
and macros from the …_TO_JSVAL family: BOOLEAN_TO_JSVAL, STRING_TO_JSVAL,
OBJECT_TO_JSVAL
可以设置两种内存使用限制。通过JS_NewRuntime可以限制每个runtime堆的大小,通过JS_NewContext可以限制每个
context栈的大小。
http://blog.chinaunix.net/u1/35985/showart_410091.html
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/181399.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...