C言語バインディング

いわゆるVSTiのような、アプリケーションプラグインのためにnmoshをつかいたい需要が最近増えてきた。今までは、nmoshのヘッダ等丸ごと使って直接的にSchemeオブジェクトを作っていたが、色々と面倒なのでpure CなAPIで簡単に使えるように整備する。
たとえばREPLを起動するだけのプログラムは:

#include <stdio.h>
#include <nmosh/vm-if.h>

int
main(int ac, char** av){
    int r;
    nmosh_object_t repl;
    nmosh_object_t param;
    nmosh_vm_t vm;
    NMOSH_EXPORT_BEGIN(px)
    NMOSH_EXPORT_END()
    nmosh_init();
    r = nmosh_vm_create(NULL, &vm); /* VMの起動 */
    printf("r = %d, vm = %lx\n",r,vm);
    /* ライブラリ(nrepl simple)からオブジェクトnreplを取得 */
    nmosh_library_lookup(vm, "(nrepl simple)", "nrepl", &repl);
    printf("repl = %lx\n",repl);
    /* NMOSH_EXPORT_BEGIN〜のオブジェクトを生成(今回はnil) */
    nmosh_object_export(px, &param);
    nmosh_vm_apply(vm, repl, param, NULL); /* replを起動 */
    return 0;
}
  • 制限: オブジェクトへのポインタは直接扱えない

オブジェクトへのポインタを直接扱うのではなく、nmosh_object_t型に一旦入れさせている。nmosh_object_tはbox化されたポインタで、BoehmGCのGC_malloc_uncollectableで確保する。こうすることで、BoehmGCの管理外のスレッドにオブジェクトへのポインタを保持させても死ぬことは無くなる。
クライアントから直接Schemeオブジェクトを操作することは今のところ想定外。listの入出力だけ出来る。

  • 制限: nmosh_vm_createしたスレッドでしか使えない

これは基本的にはBoehmGCの制限で、BohemGCが知らないスレッドでGC_malloc等を行うとGCが発生してしまう可能性があるため。
また、readerがTLS上のVMインスタンスを使用する都合上、nmoshのVMは属スレッドになっている。

  • 制限: 対話環境は操作できない

いわゆるinteraction-environment (REPLで操作している環境)を、このAPIで扱うことはできない。R6RSの制限である"ライブラリがエクスポートしている束縛はimmutable"に依存している。