How to embed the JavaScript engine

 

特により良いコードの例として JSAPI User Guide も参照して下さい。

チュートリアル要点

Hello World サンプル組み込みアプリケーション

以下のコードは非常に簡単なアプリケーションです。それは、SpiderMonkeyを組み込みかたと、簡単なJavaScriptのスクリプトを実行させること示します。以下のコードのサンプルを実行、構成する命令を参照して下さい。

/*
 * This define is for Windows only, it is a work-around for bug 661663.
 */
#ifdef _MSC_VER
# define XP_WIN
#endif

/* Include the JSAPI header file to get access to SpiderMonkey. */
#include "jsapi.h"

/* The class of the global object. */
static JSClass global_class = {
    "global", JSCLASS_GLOBAL_FLAGS,
    JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
    JSCLASS_NO_OPTIONAL_MEMBERS
};

/* The error reporter callback. */
void reportError(JSContext *cx, const char *message, JSErrorReport *report)
{
    fprintf(stderr, "%s:%u:%s\n",
            report->filename ? report->filename : "<no filename=\"filename\">",
            (unsigned int) report->lineno,
            message);
}

int main(int argc, const char *argv[])
{
    /* JSAPI variables. */
    JSRuntime *rt;
    JSContext *cx;
    JSObject  *global;

    /* Create a JS runtime. You always need at least one runtime per process. */
    rt = JS_NewRuntime(8 * 1024 * 1024);
    if (rt == NULL)
        return 1;

    /* 
     * Create a context. You always need a context per thread.
     * Note that this program is not multi-threaded.
     */
    cx = JS_NewContext(rt, 8192);
    if (cx == NULL)
        return 1;
    JS_SetOptions(cx, JSOPTION_VAROBJFIX | JSOPTION_JIT | JSOPTION_METHODJIT);
    JS_SetVersion(cx, JSVERSION_LATEST);
    JS_SetErrorReporter(cx, reportError);

    /*
     * Create the global object in a new compartment.
     * You always need a global object per context.
     */
    global = JS_NewCompartmentAndGlobalObject(cx, &global_class, NULL);
    if (global == NULL)
        return 1;

    /*
     * Populate the global object with the standard JavaScript
     * function and object classes, such as Object, Array, Date.
     */
    if (!JS_InitStandardClasses(cx, global))
        return 1;

    /* Your application code here. This may include JSAPI calls
     * to create your own custom JavaScript objects and to run scripts.
     *
     * The following example code creates a literal JavaScript script,
     * evaluates it, and prints the result to stdout.
     *
     * Errors are conventionally saved in a JSBool variable named ok.
     */
    char *script = "'Hello ' + 'World!'";
    jsval rval;
    JSString *str;
    JSBool ok;
    const char *filename = "noname";
    uintN lineno = 0;

    ok = JS_EvaluateScript(cx, global, script, strlen(script),
                           filename, lineno, &rval);
    if (rval == NULL | rval == JS_FALSE)
        return 1;

    str = JS_ValueToString(cx, rval);
    printf("%s\n", JS_EncodeString(cx, str));

    /* End of your application code */

    /* Clean things up and shut down SpiderMonkey. */
    JS_DestroyContext(cx);
    JS_DestroyRuntime(rt);
    JS_ShutDown();
    return 0;
}

Hello Worldの例のビルドと実行

ここにLinuxのコマンドラインサンプルを示します。 (ここで <objdir> はSpiderMonkeyが作られるディレクトリです):
    g++ -I<objdir>/dist/include -L<objdir>/dist/bin -lmozjs185  helloworld.cpp -o helloworld
   
これはMozillaBuildシェルからウィンドウズのコマンドラインのサンプルです:
    cl helloworld.cpp -link dist/lib/mozjs185-1.0.lib
   
とプリントされます。 Hello World!
   
  1. SpiderMOnkeyをビルドするために必要不可欠となる: Linux, Windows, Mac OS X, others等のビルドコンピュータの環境を確かめて下さい。Windowsの場合、以下の手続きを経て、 MozillaBuild パッケージをインストールすることを想定しています。
  2. SpiderMOnkeyのソースコードを入手します。 ソースアーカイブをダウンロード するか Mercurial (hg) を使って pull the SpiderMonkey レポジトリから引っ張ってきます。WindowsではMSYSrootディレクトリ (通常 c:\mozilla-build\msys)のSpiderMonkeyのソースコードをダウンロードしないで下さい。代わりに c:\js-1.8.5等を用いて下さい。
  3. Compile SpiderMonkey using the build instructions at SpiderMonkeyビルドドキュメンテーションにあるビルド命令を用いてSpiderMonkeyをコンパイルして下さい。 デフォルトではSpiderMonkeyは、後のステップでアプリケーションとリンクすることになる共有ライブラリにビルドされます。
  4. 上述のコードの例をテキストエディタにコピーして、 helloworld.cpp というファイル名で SpiderMonkey js\src  ディレクトリ内に保存して下さい。 To サンプルコードのコピーをとるためにサンプルの最上段から終端までマウス等で選択し、 view source ボタンをクリックして表示されているウィンドウからコードをコピーして下さい。
  5. helloworldアプリケーションをコンパイルし、SpiderMonkeyライブラリにリンンクします。
  6.     cl helloworld.cpp -link dist/lib/mozjs185-1.0.lib
  7.  helloworld 実行可能ファイルをコマンドラインから走らせます。:
        ./helloworld

JavaScriptからC関数の呼び出し方

doit という名前のC関数について言及します。これは呼び出されるときに少なくとも二つの実際のパラメータを使います。(もし呼びだし元がより少ないパラメータを使う場合、JSエンジンは無くなった一つの変数に対して未定義の変数が渡される事を確認すべきです):

#define DOIT_MINARGS 2

static JSBool
doit(JSContext *cx, unsigned argc, jsval *vp)
{
    jsval *argv = JS_ARGV(cx, vp);
    /*
     * Look in argv for argc actual parameters, set *rval to return a
     * value to the caller.
     */
    ...
}

そして、以下のようにコーディングし、JSに渡します:

ok = JS_DefineFunction(cx, global, "doit", doit, DOIT_MINARGS, 0);

または、ネイティブな関数群として定義するならば、おそらくそれらをテーブルの中に置き、関数テーブルとして定義するでしょう:

static JSFunctionSpec my_functions[] = {
    {"doit", doit, DOIT_MINARGS, 0, 0},
    etc...
    {0,0,0,0,0},
};

(最終的に、すべてのNULL 関数はテーブルを終端します)そして、以下のようにします:

ok = JS_DefineFunctions(cx, global, my_functions);

CからJavaScriptの関数の呼び出し方

クリックイベントを最上位のUIから座標(x,y)のUI要素に焦点をあてます:

JSObject *target, *event;
jsval argv[1], rval;

/*
 * Find event target and make event object to represent this click.
 * Pass cx to NewEventObject so JS_NewObject can be called.
 */
target = FindEventTargetAt(cx, global, x, y);
event = NewEventObject(cx, "click", x, y);
argv[0] = OBJECT_TO_JSVAL(event);

/* To emulate the DOM, you might want to try "onclick" too. */
ok = JS_CallFunctionName(cx, target, "onClick", 1, argv, &rval);

/* Now test rval to see whether we should cancel the event. */
if (JSVAL_IS_BOOLEAN(rval) && !JSVAL_TO_BOOLEAN(rval))
    CancelEvent(event);

繰り返しますが、ここではエラーチェックは無視しています。(関数呼び出し後の 戻り値 !ok のテストような)、いくつかのCのイベント管理処理やハンドラーが偽値を返したときのイベントをキャンセルする場合のDOMの伝統的なやり方を適切にエミュレートするために疑似コードを用いています。

Original Document Information

  • Author: Brendan Eich
  • Last Updated Date: 21 February, 2000

 

ドキュメントのタグと貢献者

 このページの貢献者: yoshitanaka
 最終更新者: yoshitanaka,