sm3.c

最終更新:2009/11/16

sm3.c

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 */
Copyright (C) KAKU PROJECT (2009)KAKU PROJECT (2009)