sm3.c
最終更新:2009/11/16
001: /* sm3.c 002: * SpiderMonkey を C プログラムから使う例 003: * スクリプトファイルで定義した関数を C プログラムの中で使用する。 004: * ・コマンドライン引数で JavaScript のファイル名を指定する。 005: * ファイルの中で定義した関数 foo にコマンドライン引数で指定した値を 006: * 引数として適用する。 007: * ・foo は整数値を引数としてとり、整数値を返す関数とする。 008: * int foo(int) 009: * ・実行例 010: * % sm3 foo.js 6 011: * のように実行した場合は、foo.js 内で定義した関数 foo に引数 6 を適用する。 012: */ 013: 014: #define USAGE "Usage: sm3 <script_file_of_foo> <arg_of_foo>" 015: 016: #define FUNC_NAME "foo" 017: 018: #include <stdio.h> 019: #include <stdlib.h> 020: #include <string.h> 021: #include "jsapi.h" 022: 023: /* グローバルオブジェクトのクラス */ 024: static JSClass global_class = { 025: "global", 026: JSCLASS_GLOBAL_FLAGS, 027: JS_PropertyStub, 028: JS_PropertyStub, 029: JS_PropertyStub, 030: JS_PropertyStub, 031: JS_EnumerateStub, 032: JS_ResolveStub, 033: JS_ConvertStub, 034: JS_FinalizeStub, 035: JSCLASS_NO_OPTIONAL_MEMBERS 036: }; 037: 038: /* 039: * 組込み関数の定義 040: */ 041: JSBool myjs_print( 042: JSContext *jsctx 043: , JSObject *obj 044: , uintN argc 045: , jsval *argv 046: , jsval *rval 047: ) { 048: uintN i = 0; 049: JSString *str = NULL; 050: char *bytes = NULL; 051: 052: for (i = 0; i < argc; i++) { 053: str = JS_ValueToString(jsctx, argv[i]); 054: if (!str) 055: return JS_FALSE; 056: bytes = JS_EncodeString(jsctx, str); 057: if (!bytes) 058: return JS_FALSE; 059: printf("%s%s", i ? " " : "", bytes); 060: JS_free(jsctx, bytes); 061: } 062: 063: *rval = JSVAL_VOID; /* return undefined */ 064: 065: return JS_TRUE; 066: } 067: 068: static JSFunctionSpec myjs_global_functions[] = { 069: JS_FS("print", myjs_print, 0, 0, 0), 070: JS_FS_END 071: }; 072: 073: /* エラーレポート用コールバック関数 */ 074: void reportError( 075: JSContext *jsctx 076: , const char *message 077: , JSErrorReport *report 078: ) { 079: fprintf(stderr, "%s:%u:%s\n", 080: report->filename ? report->filename : "", 081: (unsigned int) report->lineno, 082: message); 083: } 084: 085: JSBool execute_script( 086: JSContext *jsctx 087: , char *filename 088: , JSScript **js_script 089: , jsval *rval 090: ) { 091: if (! filename) { 092: return JS_FALSE; 093: } 094: *js_script = JS_CompileFile(jsctx, JS_GetGlobalObject(jsctx), filename); 095: if (! *js_script) { 096: return JS_FALSE; 097: } 098: return JS_ExecuteScript(jsctx, JS_GetGlobalObject(jsctx), *js_script, rval); 099: } 100: 101: JSBool call_function ( 102: JSContext *jsctx 103: , const char *func_name 104: , int argc 105: , int *args 106: , int *ret 107: ) { 108: uintN jargc = argc; 109: jsval *jargs = NULL; 110: 111: if (!func_name) { 112: return JS_FALSE; 113: } 114: 115: jargs = (jsval*)malloc(sizeof(jsval)*argc); 116: { 117: int i=0; 118: for (; i<argc; i++) { 119: jargs[i] = INT_TO_JSVAL(args[i]); 120: } 121: } 122: { 123: jsval rval; 124: JSBool ok = JS_CallFunctionName(jsctx, JS_GetGlobalObject(jsctx), 125: func_name, jargc, jargs, &rval); 126: free(jargs); 127: if (ok == JS_TRUE) { 128: 129: #if 0 130: { 131: JSString *str = JS_ValueToString(jsctx, rval); 132: if (str) { 133: printf("rval: %s\n", JS_GetStringBytes(str)); 134: } 135: } 136: #endif 137: 138: return JS_ValueToInt32(jsctx, rval, ret); 139: } 140: } 141: return JS_FALSE; 142: } 143: 144: int main(int ac, char **av) 145: { 146: int error_flag = 0; 147: 148: JSRuntime *jsrt = NULL; 149: JSContext *jsctx = NULL; 150: JSObject *global = NULL; 151: 152: char *filename = NULL; 153: int foo_arg = 0; 154: 155: if (ac < 3) { 156: fprintf(stderr, "%s\n", USAGE); 157: error_flag = 1; 158: goto _FINALLY_; 159: } 160: filename = av[1]; 161: foo_arg = atoi(av[2]); 162: 163: /* 初期化 */ 164: 165: /* プロセス単位でランタイムを生成 */ 166: jsrt = JS_NewRuntime(8L * 1024L * 1024L); 167: if (!jsrt) { 168: fprintf(stderr, "ERROR: JS_NewRuntime "); 169: error_flag = 1; 170: goto _FINALLY_; 171: } 172: 173: /* スレッド単位でコンテクスト生成 */ 174: jsctx = JS_NewContext(jsrt, 8192); 175: if (!jsctx) { 176: fprintf(stderr, "ERROR: JS_NewContext "); 177: error_flag = 1; 178: goto _FINALLY_; 179: } 180: 181: JS_SetOptions(jsctx, JSOPTION_VAROBJFIX); 182: JS_SetVersion(jsctx, JSVERSION_LATEST); 183: JS_SetErrorReporter(jsctx, reportError); 184: 185: /* コンテクスト単位でグローバルオブジェクトを生成 */ 186: global = JS_NewObject(jsctx, &global_class, NULL, NULL); 187: if (!global) { 188: fprintf(stderr, "ERROR: JS_NewObject "); 189: error_flag = 1; 190: goto _FINALLY_; 191: } 192: 193: if (!JS_InitStandardClasses(jsctx, global)) { 194: fprintf(stderr, "ERROR: JS_InitStandardClasses "); 195: error_flag = 1; 196: goto _FINALLY_; 197: } 198: 199: if (!JS_DefineFunctions(jsctx, global, myjs_global_functions)) { 200: fprintf(stderr, "ERROR: JS_DefineFunctions "); 201: error_flag = 1; 202: goto _FINALLY_; 203: } 204: 205: /* スクリプトの実行 */ 206: 207: { 208: JSScript *js_script = NULL; 209: jsval rval; 210: if(!execute_script(jsctx, filename, &js_script, &rval)) { 211: fprintf(stderr, "ERROR: execute_script "); 212: error_flag = 1; 213: goto _FINALLY_; 214: } 215: if (js_script) { 216: //JS_MaybeGC(jsctx); 217: JS_DestroyScript(jsctx, js_script); /* このスクリプトは再利用しない */ 218: } 219: } 220: 221: /* 関数 foo の実行 */ 222: { 223: int ret = 0; 224: int args[1]; 225: args[0] = foo_arg; 226: if (! call_function(jsctx, FUNC_NAME, 1, args, &ret)) { 227: fprintf(stderr, "ERROR: call_function "); 228: error_flag = 1; 229: goto _FINALLY_; 230: } 231: printf("%s(%d)=%d\n", FUNC_NAME, args[0], ret); 232: } 233: 234: _FINALLY_: 235: 236: /* JSContext と JSRuntime リソースの解放 */ 237: if (jsctx) { 238: JS_DestroyContext(jsctx); 239: jsctx = NULL; 240: } 241: if (jsrt) { 242: JS_DestroyRuntime(jsrt); 243: jsrt = NULL; 244: } 245: 246: JS_ShutDown(); 247: 248: if (error_flag) { 249: fprintf(stderr, "failed.\n"); 250: return 1; 251: } 252: 253: /* 254: printf("done.\n"); 255: */ 256: return 0; 257: } /* End of main */
KAKU PROJECT (2009) |