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) |