こんにちは、鈴木です。
「C言語からGaucheを使おう!」シリーズです。
前回の「C言語からGaucheを使おう! (8) Scm_LoadFromPortでloadする」では文字列リテラルから入力ポートを作成し、そこから load する方法を調べました。
今回はファイルに保存された Scheme コードを読み込む方法を調べます。
Scm_Load 関数
まずは Scheme コードをファイルに保存しておきます。
カレントディレクトリに a.scm というファイルを作成し、以下の内容を記述します。
1 2 3 4 5 |
(define sum (lambda (xs) (apply + xs))) (define average (lambda (xs) (/ (sum xs) (length xs)))) |
合計を求める手続き sum と、平均を求める手続き average を定義しています。
a.scm を読み込むには、以下のようにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
#include <stdio.h> #include <gauche.h> /** * ScmEvalPacket や ScmLoadPacket に含まれる例外情報を表示します. */ #define PRINT_EXCEPTION(packet) \ printf("[%s] %s\n", \ SCM_STRING_CONST_CSTRING(Scm_ConditionTypeName(packet.exception)), \ SCM_STRING_CONST_CSTRING(Scm_ConditionMessage(packet.exception))); void load() { ScmLoadPacket load_packet; Scm_AddLoadPath(".", TRUE); if(Scm_Load("a.scm", 0, &load_packet) < 0) { PRINT_EXCEPTION(load_packet); return; } } void apply_something() { ScmObj procedure; ScmObj arguments; ScmEvalPacket eval_packet; /* (apply sum '((1 2 3))) */ procedure = Scm_GlobalVariableRef(Scm_UserModule(), SCM_SYMBOL(SCM_INTERN("sum")), SCM_BINDING_STAY_IN_MODULE); arguments = SCM_LIST1(SCM_LIST3(SCM_MAKE_INT(1), SCM_MAKE_INT(2), SCM_MAKE_INT(3))); if(Scm_Apply(procedure, arguments, &eval_packet) < 0) { PRINT_EXCEPTION(eval_packet); return; } Scm_Printf(SCM_CUROUT, "%S\n", eval_packet.results[0]); /* (apply average '((1 2 3))) */ procedure = Scm_GlobalVariableRef(Scm_UserModule(), SCM_SYMBOL(SCM_INTERN("average")), SCM_BINDING_STAY_IN_MODULE); arguments = SCM_LIST1(SCM_LIST3(SCM_MAKE_INT(1), SCM_MAKE_INT(2), SCM_MAKE_INT(3))); if(Scm_Apply(procedure, arguments, &eval_packet) < 0) { PRINT_EXCEPTION(eval_packet); return; } Scm_Printf(SCM_CUROUT, "%S\n", eval_packet.results[0]); } int main() { GC_INIT(); Scm_Init(GAUCHE_SIGNATURE); load(); apply_something(); return 0; } |
内容は「C言語からGaucheを使おう! (8) Scm_LoadFromPortでloadする」のサンプルコードとほとんど同じで、sample_load_from_port 関数が sample_load 関数に変わっているだけです。
実行すると、以下の結果が得られます。(※「C言語からGaucheを使おう! (1) コンパイル環境を整える」で作成した Makefile を使用します)
1 2 3 |
> make run 6 2 |
前回同様、出力の 1 行目は「(apply sum '((1 2 3)))」の結果、2 行目が「(apply average '((1 2 3)))」の結果です。
load 関数
load 関数を詳しく見ていきましょう。
1 2 3 4 5 6 7 8 9 10 11 |
void load() { ScmLoadPacket load_packet; Scm_AddLoadPath(".", TRUE); if(Scm_Load("a.scm", 0, &load_packet) < 0) { PRINT_EXCEPTION(load_packet); return; } } |
まず、Scm_AddLoadPath 関数でカレントディレクトリをロードパスに追加しています(初期状態ではカレントディレクトリはロードパスに含まれていません)。
次に Scm_Load 関数を用いて、先ほど作成した a.scm を読み込んでいます。
まとめ
今回はファイルとして保存されている Scheme プログラムを読み込む方法を調べました。
今までの内容で Gauche を組み込み言語として使うための準備が整いました。
C 言語で拡張できる他の言語(Ruby や Python、Java など)にも Gauche を組み込めるということですね。