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