myjs.c
最終更新:2009/11/18
001: /* myjs.c
002: * SpiderMonkey を C プログラムから使う例
003: */
004:
005: #include <stdio.h>
006: #include <stdlib.h>
007: #include <string.h>
008: #include "myjs.h"
009:
010: #ifndef MY_JS_DEBUG
011: #define MY_JS_DEBUG 0
012: #endif
013:
014: /* JSRuntime */
015: static JSRuntime *jsrt = NULL;
016:
017: /* グローバルオブジェクトのクラス */
018: static JSClass global_class = {
019: "global",
020: JSCLASS_GLOBAL_FLAGS,
021: JS_PropertyStub,
022: JS_PropertyStub,
023: JS_PropertyStub,
024: JS_PropertyStub,
025: JS_EnumerateStub,
026: JS_ResolveStub,
027: JS_ConvertStub,
028: JS_FinalizeStub,
029: JSCLASS_NO_OPTIONAL_MEMBERS
030: };
031:
032: /*
033: * 組込み関数の定義
034: */
035: static JSBool myjs_print(
036: JSContext *jsctx
037: , JSObject *obj
038: , uintN argc
039: , jsval *argv
040: , jsval *rval
041: ) {
042: uintN i = 0;
043: JSString *str = NULL;
044: char *bytes = NULL;
045:
046: for (i = 0; i < argc; i++) {
047: str = JS_ValueToString(jsctx, argv[i]);
048: if (!str)
049: return JS_FALSE;
050: bytes = JS_EncodeString(jsctx, str);
051: if (!bytes)
052: return JS_FALSE;
053: printf("%s%s", i ? " " : "", bytes);
054: JS_free(jsctx, bytes);
055: }
056:
057: *rval = JSVAL_VOID; /* return undefined */
058:
059: return JS_TRUE;
060: }
061:
062: static JSFunctionSpec myjs_global_functions[] = {
063: JS_FS("print", myjs_print, 0, 0, 0),
064: JS_FS_END
065: };
066:
067: /* エラーレポート用コールバック関数 */
068: static void reportError(
069: JSContext *jsctx
070: , const char *message
071: , JSErrorReport *report
072: ) {
073: fprintf(stderr, "%s:%u:%s\n",
074: report->filename ? report->filename : "",
075: (unsigned int) report->lineno,
076: message);
077: }
078:
079: /*
080: * スクリプトファイルを読み込んで実行
081: * 返り値:
082: * 1:成功
083: * 0:失敗
084: */
085:
086: int my_js_execute_script(
087: JSContext *jsctx /* IN: JSContext */
088: , char *filename /* IN: スクリプトファイル */
089: , JSScript **js_script_p /* OUT: コンパイル済みスクリプト */
090: , jsval *rval /* OUT: スクリプトで最後に評価した式の結果 */
091: ) {
092: int ret = JS_FALSE;
093: JSScript *js_script=NULL;
094:
095: if (!filename) {
096: return 0;
097: }
098:
099: js_script = JS_CompileFile(jsctx, JS_GetGlobalObject(jsctx), filename);
100: if (! js_script) {
101: return 0;
102: }
103:
104: ret = JS_ExecuteScript(jsctx, JS_GetGlobalObject(jsctx), js_script, rval);
105: if (ret != JS_TRUE) {
106: return 0;
107: }
108: if (js_script_p) {
109: *js_script_p = js_script;
110: }
111:
112: return 1;
113: }
114:
115: /* 関数の実行 int[]→int
116: * 返り値:
117: * 1:成功
118: * 0:失敗
119: */
120:
121: int my_js_call_function_IA_I (
122: JSContext *jsctx /* IN: JSContext */
123: , const char *func_name /* IN: 関数名 */
124: , int argc /* IN: 引数の個数 */
125: , int *args /* IN: 引数の配列 */
126: , int *ret /* OUT: 関数の実行結果 */
127: ) {
128: uintN jargc = argc;
129: jsval *jargs = NULL;
130:
131: if (!func_name) {
132: return 0;
133: }
134:
135: jargs = (jsval*)malloc(sizeof(jsval)*argc);
136: {
137: int i=0;
138: for (; i<argc; i++) {
139: jargs[i] = INT_TO_JSVAL(args[i]);
140: }
141: }
142: {
143: jsval rval;
144: JSBool ok = JS_CallFunctionName(jsctx, JS_GetGlobalObject(jsctx),
145: func_name, jargc, jargs, &rval);
146: free(jargs);
147: if (ok == JS_TRUE) {
148:
149: if (MY_JS_DEBUG) {
150: JSString *str = JS_ValueToString(jsctx, rval);
151: if (str) {
152: printf("rval: %s\n", JS_GetStringBytes(str));
153: }
154: }
155:
156: if (JS_ValueToInt32(jsctx, rval, ret) == JS_TRUE) {
157: return 1;
158: }
159: }
160: }
161: return 0;
162: }
163:
164: /* 関数の実行 char**→char*
165: * 返り値:
166: * 1:成功
167: * 0:失敗
168: */
169:
170: int my_js_call_function_SA_S (
171: JSContext *jsctx /* IN: JSContext */
172: , const char *func_name /* IN: 関数名 */
173: , int argc /* IN: 引数の個数 */
174: , char **args /* IN: 引数の配列 */
175: , char **ret /* OUT: 関数の実行結果 */
176: ) {
177: uintN jargc = argc;
178: jsval *jargs = NULL;
179:
180: if (!func_name) {
181: return 0;
182: }
183:
184: jargs = (jsval*)malloc(sizeof(jsval)*argc);
185: {
186: int i=0;
187: for (; i<argc; i++) {
188: JSString *jstr = JS_NewString(jsctx, args[i], strlen(args[i]));
189: jargs[i] = STRING_TO_JSVAL(jstr);
190: }
191: }
192: {
193: jsval rval;
194: JSBool ok = JS_CallFunctionName(jsctx, JS_GetGlobalObject(jsctx),
195: func_name, jargc, jargs, &rval);
196: free(jargs);
197: if (ok == JS_TRUE) {
198: JSString *str = JS_ValueToString(jsctx, rval);
199: if (str) {
200: *ret = JS_GetStringBytes(str);
201: return 1;
202: }
203: }
204: }
205: return 0;
206: }
207:
208: /*
209: * JSRuntime の初期化
210: * ・プロセス単位で実行すること
211: * 返り値:
212: * 1:成功
213: * 0:失敗
214: */
215:
216: int my_js_rt_init()
217: {
218:
219: if (jsrt) {
220: return 0; /* 初期化済み */
221: }
222:
223: jsrt = JS_NewRuntime(MY_JS_MAXBYTES);
224: if (!jsrt) {
225: if(MY_JS_DEBUG)fprintf(stderr, "ERROR: JS_NewRuntime\n");
226: return 0;
227: }
228:
229: return 1;
230: }
231:
232: /*
233: * JSContext の生成
234: * ・スレッド単位で実行すること
235: * 返り値:
236: * NULL:失敗
237: */
238: JSContext *my_js_ctx_init()
239: {
240: int error_flag = 0;
241:
242: JSContext *jsctx = NULL;
243: JSObject *global = NULL;
244:
245: if (!jsrt) {
246: if(MY_JS_DEBUG)fprintf(stderr, "ERROR: my_js_ctx_init\n");
247: return NULL; /* JSRuntime 初期化前 */
248: }
249:
250: jsctx = JS_NewContext(jsrt, MY_JS_STACKSIZE);
251: if (!jsctx) {
252: if(MY_JS_DEBUG)fprintf(stderr, "ERROR: JS_NewContext\n");
253: error_flag = 1;
254: goto _FINALLY_;
255: }
256:
257: JS_SetOptions(jsctx, JSOPTION_VAROBJFIX);
258: JS_SetVersion(jsctx, JSVERSION_LATEST);
259: JS_SetErrorReporter(jsctx, reportError);
260:
261: /* コンテクスト単位でグローバルオブジェクトを生成 */
262: global = JS_NewObject(jsctx, &global_class, NULL, NULL);
263: if (!global) {
264: if(MY_JS_DEBUG)fprintf(stderr, "ERROR: JS_NewObject\n");
265: error_flag = 1;
266: goto _FINALLY_;
267: }
268:
269: if (!JS_InitStandardClasses(jsctx, global)) {
270: if(MY_JS_DEBUG)fprintf(stderr, "ERROR: JS_InitStandardClasses\n");
271: error_flag = 1;
272: goto _FINALLY_;
273: }
274:
275: if (!JS_DefineFunctions(jsctx, global, myjs_global_functions)) {
276: if(MY_JS_DEBUG)fprintf(stderr, "ERROR: JS_DefineFunctions\n");
277: error_flag = 1;
278: }
279:
280: _FINALLY_:
281: if (error_flag) {
282: return NULL;
283: }
284:
285: return jsctx;
286: }
287:
288: /*
289: * JSContext の解放
290: */
291: void my_js_ctx_clear(
292: JSContext *jsctx
293: ) {
294: if (jsctx) {
295: JS_DestroyContext(jsctx);
296: }
297: }
298:
299: /*
300: * JSRuntime の解放
301: */
302: void my_js_rt_clear() {
303: if (jsrt) {
304: JS_DestroyRuntime(jsrt);
305: jsrt = NULL;
306: }
307:
308: JS_ShutDown();
309: }
![]() | KAKU PROJECT (2009) |