PERLCALL(1) USER COMMANDS PERLCALL(1) NAME perlcall - Perl の C からの呼び出し法 DESCRIPTION WARNING : このドキュメントは、現在まだ作成中です。 不正確な 点が、たくさんあることは確実ですので、とうぶんは、注意して読 むようにしてください。 このドキュメントの目的は、「コールバック」の書き方、すなわち、 どのように C から Perl を呼び出すかを示すことです。 中心と なるのは、Perl によって実行される、ほんのわずかの C のコード から Perl を呼び戻すインタフェース、つまり、'main' プログラ ムは Perl スクリプトで、そこから C で書いたコードを起動し、 その C のコードが何かを行なうときに、特定のイベントによって、 Perl sub を実行するということが、いつでもできるようにしてお くことが必要でしょう。 必要に応じて、例を示すようにしてあります + アプリケーションの C API へのインタフェース XSUB を作成 しました。 アプリケーションでかなり一般的な機能として、なにか面倒 が起こったときに、呼ぶことのできる C の関数を定義するこ とができるようにすることがあげられます。 やりたいこと は、代わりに Perl sub を呼ぶということです。 + どこでコールバックが使われるかの古典的な例は、X-windows のようなイベントドリブンなプログラムに見られます。 こ の場合、登録内容は、マウスのボタンが押されたような、特 定のイベントが発生したときに呼ばれるように機能します。 記述したテクニックは、Perl プログラムを C プログラムに埋め込 むときにも適用することができますが、これは、このドキュメント の本来の目的ではありません。 C に埋め込む Perl に関する詳細 は、perlembed manpage (現在執筆中) を参照してください。 このドキュメントの残りの部分に進む前に、以下の 2 つのドキュ メントを読んでおいた方が良いでしょう。 - perlapi manpage と perlguts manpage です。 内容は、例を用いて、やさしく説明しています。 しかし、まず、 とにかく定義をいくつかしておきましょう。 定義 Perl では、Perl sub を呼ぶことを許している C の関数がたくさ んあります。 それは、 Perl manpages Last change: Release 5.0 Patchlevel 00 1 PERLCALL(1) USER COMMANDS PERLCALL(1) I32 perl_call_sv(SV* sv, I32 flags) ; I32 perl_call_pv(char *subname, I32 flags) ; I32 perl_call_method(char *methname, I32 flags) ; I32 perl_call_argv(char *subname, I32 flags, register char **argv) ; 中心となる関数は、perl_call_sv です。 他の関数は、自分のや りたいことに合わせて、perl_call_sv を利用します。 perl_call _sv は、2 つの引数をとり、最初の引数は、 SV* です。 これに よって、呼び出される Perl sub を C の文字列 (まず、SV に変換 されています) か、sub へのリファレンスで指定することができま す。 例 7 では、自ら perl_call_sv を利用する方法を示します。 2 番目のパラメータ flags は、汎用のオプションコマンドです。 このパラメータは、すべての perl_call_* 関数に共通です。 詳 しくは、次の節で述べます。 関数 perl_call_pv は、ほぼ perl_call_sv と同じですが、最初の 引数として呼び出したい Perl sub を示す C の char * を指定し ます。 例: perl_call_pv("fred", 0) 関数 perl_call_method は、最初の引数に、bless された、クラス へのリファレンスを指定しなければなりません。 そのリファレン スを使って検索し、該当クラスから methname を呼び出します。 例 9 を参照。 perl_call_argv は、subname パラメータで指定された Perl sub を 呼び出します。 これはまた、通常の flags パラメータも指定し ます。 最後のパラメータ argv には、Perl sub に渡される C の 文字列のリストを指定します。 例 8 を参照してください。 すべての関数は、数を返します。 これは、Perl sub がスタック 上に置いた、返却物の数を示します。 一般論として、これらの関数からの返却値は「常に」チェックして ください。 Perl sub から特定の数が返って来ることを期待して いる場合にも、誰かがなにか期待以外のことをしないとは限りませ ん。 「そんなの聞いていない」とは言わないでください。 フラグ値 すべての perl_call_* 関数のパラメータ flags は、以下に定義す るシンボルを「論理和」で組み合わせて用います。 G_SCALAR Perl sub をスカラコンテキストで呼び出します。 Perl sub が実際に何を返そうとも、スカラのみが必要と解釈 されます。 Perl sub がスカラを返したときには、perl_call_* 関数の返却値は、1 か 0 になります。 1 ならば、Perl sub が実際に返した値は、スタックのトップにあります。 0 な らば、sub で die を呼んだか、G_DISCARD フラグを設定した ことを示します。 Perl manpages Last change: Release 5.0 Patchlevel 00 2 PERLCALL(1) USER COMMANDS PERLCALL(1) Perl sub がリストを返すときにも、perl_call_* 関数は、0 か 1 を返します。 1 であれば、リストの要素の数がスタッ クのトップに置かれます。 実際のリストの値には、アクセ スできなくなります。 G_SCALAR は、すべての関数で、デフォルトで設定されている フラグです。 G_ARRAY Perl sub をリストコンテキストで呼び出します。 perl_call_* 関数からの返却値は、積まれた配列がスタック を何要素使ったかを示します。 G_DISCARD Perl sub からの返却値が必要ないときには、このフラグを設 定することで、Perl が自動的に廃棄してくれます。 このフ ラグは、G_SCALAR や G_ARRAY よりも優先されます。 このフラグを設定しなかった場合には、一時的な値を明示的 に自分で処分する必要があるかもしれません。 詳細は、例 3 を参照してください。 G_NOARGS Perl sub に対して、何の引数も渡さないときには、このフラ グを設定することで、時間を少し稼ぐことができます。 こ れは、Perl sub に対して、新しく @_ を生成しないという効 果があります。 言うまでもないことですが、このフラグが指定された場合に も、呼び出された Perl sub からは、上位の Perl sub の @_ をアクセスすることができます。 この機能は、以下のよう な perl コードで確かめることができます。 sub fred { print "@_\n" } sub joe { &fred } &joe(1,2,3) ; とすると 1 2 3 と表示します。 joe に属している配列 @_ を fred からア クセスしたのです。 Perl manpages Last change: Release 5.0 Patchlevel 00 3 PERLCALL(1) USER COMMANDS PERLCALL(1) G_EVAL 呼び出す Perl sub が、die を呼んだり、実際に exit する など、通常ではない終了の仕方をすることがあり、そのよう なイベントを捕捉したいようなときに、このフラグを設定し ます。 sub の呼び出しを eval { } で囲ったような状態に する働きがあります。 perl_call_* 関数から制御が戻ったときには、通常 Perl ス クリプトで行なうように、変数 $@ をチェックする必要があ ります。 チェックの仕方については、例 6 を参照してくだ さい。 EXAMPLES 定義の話は十分でしょうから、いくつか例を示します。 Perl では、Perl スタックをアクセスする手助けのためのマクロを たくさん用意しています。 Perl の内部ルーティンとのインタフ ェースには、常にこれらのマクロを使うようにすべきでしょう。 将来 Perl に施される変更に対しても、これを使うことで、コード の方への影響が少なくなるはずです。 もう一つ余計なことを言っておくと、最初のいくつかの例では、 perl_call_pv 関数だけを使っています。 これは、単にみなさん がこの話題に入り込みやすいようにと考えただけのことです。 perl_call_pv と perl_call_sv のどちらも使える場合、私は常に perl_call_sv を使います。 これらの例のコードは、perlcall.tar というファイルに納められ ています。 (いったん、このドキュメントが落ち着いたら、すべ ての例のコードをファイルに入れるようにします。) 例 1: パラメータなし、返却値なし 最初の明快な例は、プロセスの UID を出力するために、Perl sub の PrintUID を呼びます。 sub PrintUID { print "UID is $<\n" ; } と、これを呼ぶ C 側です void call_PrintUID() { dSP ; PUSHMARK(sp) ; perl_call_pv("PrintUID", G_DISCARD|G_NOARGS) ; } Perl manpages Last change: Release 5.0 Patchlevel 00 4 PERLCALL(1) USER COMMANDS PERLCALL(1) 単純でしょう。 この例についていくつか注意点をあげておきましょう。 1. PrintUID に引数を渡しませんので、G_NOARGS を指定できま す。 2. 今のところ、dSP と PUSHMARK(sp) は無視してください。 これについては、次の例でお話します。 3. PrintUID から返されるものは、特に必要ありませんので、 G_DISCARD を指定しています。 PrintUID が何か値を返す ように変更されても、G_DISCARD を指定しておくと、perl_ call_pv から制御が戻るときに、その値が捨てられることに なります。 4. G_DISCARD を指定しましたので、perl_call_sv からの返却値 をチェックする必要はありません。 常に 0 となります。 5. perl_call_pv が使われていますから、Perl sub は C の文字 列として表現されています。 例 2: パラメータを渡す さて、今度はもう少し込み入った例です。 今回は、2 つの引数と して、文字列 ($a) と整数 ($n) をとる Perl sub を呼び出してみ ましょう。 sub では、簡単に、文字列の最初の $n 文字を出力し ます。 Perl sub は以下のようなものです: sub LeftString { my($s, $n) = @_ ; print substr($s, 0, $n), "\n" ; } LeftString を呼ぶための C の関数は、以下のようです: static void call_LeftString(a, b) char * a ; int b ; { dSP ; PUSHMARK(sp) ; XPUSHs(sv_2mortal(newSVpv(a, 0))); XPUSHs(sv_2mortal(newSViv(b))); PUTBACK ; Perl manpages Last change: Release 5.0 Patchlevel 00 5 PERLCALL(1) USER COMMANDS PERLCALL(1) perl_call_pv("LeftString", G_DISCARD); } C の関数 call_LeftString の注意点を示します。 1. 今回指定しているフラグは、G_DISCARD のみです。 今回、 Perl sub に 2 つのパラメータを渡しますので、G_NOARGS は 指定していません。 2. パラメータは、Perl スタックを使って Perl sub に渡されま す。 これが、dSP で始め、PUTBACK 行で終わるコードの目 的です。 3. Perl スタックに何かをおこうとする場合には、どこにおけば よいかを知る必要があります。 これが、マクロ dSP の目的 で、Perl スタックポインタのローカルなコピーを宣言し、初 期化します。 この例で使う、他のすべてのマクロは、このマクロの使用を 前提にしています。 Perl sub を直接 XSUB 関数から呼ぶときには、明示的に dSP マクロを使う必要はありません。 自動的に宣言されます。 4. スタック上に積まれるパラメータはすべて、PUSHMARK マクロ と PUTBACK マクロで囲まなければなりません。 この 2 つ のマクロは、この文脈では、自動的にプッシュした引数の数 を数えるために使われます。 それで、Perl が sub に対し て @_ 配列を作るときには、その大きさがわかるという仕組 みになっているのです。 PUSHMARK マクロは、Perl に対して、内的にその時点のスタ ックポインタに注目するように伝えます。 (例 1 の場合の ように) 引数を渡さない場合であっても、perl_call_* 関数 を呼ぶ場合には、その前に PUSHMARK マクロを呼ばなくては なりません。 Perl からすると、引数がないことを知る必要 があるのです。 少し先へ飛んで、PUTBACK マクロは、グローバルなスタック ポインタを、先に作ったローカルなものに合わせます。 こ れを行わないと、どこに引数を置いたか、perl_call_pv が判 断することができません。 ここまで、すべてのスタックポ インタの操作は、ローカルなものに対して行なってきたので あって、グローバルなものは触っていなかったのです。 5. 元に戻って、次に XPUSH を引数分呼んでいます。 ここで、 実際に引数がスタックに積まれます。 今回の場合、文字列 と整数を積んでいます。 XPUSH マクロがどのように動作するのかについて詳しくは、 perlguts manpage の「XSUB と引数スタック」の項を参照し てください。 Perl manpages Last change: Release 5.0 Patchlevel 00 6 PERLCALL(1) USER COMMANDS PERLCALL(1) 6. ここまでで、LeftString を perl_call_pv 関数を介して呼ぶ ことができます。 例 3: スカラを返す さて、Perl sub からの返却値を扱う例を見てみましょう。 ここにあげる Perl sub は、2 つの整数引数をとって、単にその和 を返す Adder というものです。 sub Adder { my($a, $b) = @_ ; $a + $b ; } Adder からの返却値を扱う必要がありますので、C 関数側は今回、 多少複雑になります。 static void call_Adder(a, b) int a ; int b ; { dSP ; int count ; ENTER ; SAVETMPS; PUSHMARK(sp) ; XPUSHs(sv_2mortal(newSViv(a))); XPUSHs(sv_2mortal(newSViv(b))); PUTBACK ; count = perl_call_pv("Adder", G_SCALAR); SPAGAIN ; if (count != 1) croak("Big trouble\n") ; printf ("The sum of %d and %d is %d\n", a, b, POPi) ; PUTBACK ; FREETMPS ; LEAVE ; } Perl manpages Last change: Release 5.0 Patchlevel 00 7 PERLCALL(1) USER COMMANDS PERLCALL(1) 注意点は、 1. 今回は、フラグとして G_SCALAR だけを使用しています。 これは、@_ 配列が作られ、Adder からの返された値は、perl _call_pv の呼び出し後も存在することを表わします。 2. Adder から返されるものに意味がありますから、G_DISCARD を指定することはできません。 つまり、自分で Perl スタ ックをきちんと整理して、一時的な値も廃棄する必要があり ます。 これが、関数の最初で、 ENTER ; SAVETMPS ; として、最後に FREETMPS ; LEAVE ; としていることの目的です。 ENTER/SAVETMPS のペアが、使 用する一時的な領域を作ります。 逆にいうと、自分で廃棄 できるものは、これらを呼び出した後に作ったものに限定さ れるということです。 FREETMPS/LEAVE のペアは、Perl sub が返した値を捨て、生 成した SV について、解放直前の情報をダンプします。 コ ードの最初に ENTER/SAVETMPS をおくことで、それ以上の開 放情報が壊されるのを防ぎます。 3. SPAGAIN マクロの目的は、ローカルなスタックポインタをリ フレッシュすることです。 perl_call_pv の呼び出しの間に 再配置された Perl スタックへメモリ配置を行なうことがで きますから、これが必要になります。 コードの中で Perl スタックポインタを利用する場合には、 perl_call_* 関数や他の Perl の内部関数を利用するときに は必ず、SPAGAIN を使ってローカルなポインタをリフレッシ ュしなくてはなりません。 4. Adder から返されるのは、単一の値のみのはずですが、いず れにしても perl_call_pv からの返却値をチェックするのが 良いでしょう。 単一の値を期待するのは、一つであることを知っていること とは違います。 誰かが Adder を改造して、リストを返すよ うにし、その可能性をチェックしていなかったときに、この 操作を行なってしまうと、Perl スタックの状態は、矛盾した ものになってしまいます。 こんなことは、誰も望みはしな いでしょう。 5. スタックから、返却値をポップするのに、ここでは POPi マ クロを使用しています。 ここでは整数が必要であったため、 Perl manpages Last change: Release 5.0 Patchlevel 00 8 PERLCALL(1) USER COMMANDS PERLCALL(1) POPi を使用したのです。 返された値の型に応じて、以下の POP マクロを使用すること ができます。 POPs SV POPp ポインタ POPn 倍精度 POPi 整数 POPl long 整数 6. 最後の PUTBACK は、関数を抜ける前に、Perl スタックを矛 盾の無い状態にしておくために使用しています。 これは、 POPi でスタックから返却値を取り出したときに、ローカルな スタックポインタのみを更新するため、必要となります。 先の例で説明したように PUTBACK は、グローバルなスタック ポインタをローカルなスタックポインタの値にあわせるよう に設定します。 例 4: リスト値を返す さて、今度は、先の例を改造して、2 つの引数の和と差の両方を返 すようにしてみましょう。 Perl sub は sub AddSubtract { my($a, $b) = @_ ; ($a+$b, $a-$b) ; } のようになり、C 関数は static void call_AddSubtract(a, b) int a ; int b ; { dSP ; int count ; ENTER ; SAVETMPS; PUSHMARK(sp) ; XPUSHs(sv_2mortal(newSViv(a))); XPUSHs(sv_2mortal(newSViv(b))); PUTBACK ; Perl manpages Last change: Release 5.0 Patchlevel 00 9 PERLCALL(1) USER COMMANDS PERLCALL(1) count = perl_call_pv("AddSubtract", G_ARRAY); SPAGAIN ; if (count != 2) croak("Big trouble\n") ; printf ("%d - %d = %d\n", a, b, POPi) ; printf ("%d + %d = %d\n", a, b, POPi) ; PUTBACK ; FREETMPS ; LEAVE ; } となります。 注意点 1. リストコンテキストが必要なため、G_ARRAY を使用します。 2. スタックから 2 つの値を取り出すため、今回 2 つの POPi を使っていることは、驚くに値しないでしょう。 それより も、注目すべきは、スタックから取り出したときに逆順とな ることです。 reverse order. 例 5: Perl から引数リストを介してデータを返す 引数リストを使って直接値を返すことも可能です。 ただし、これ が実際に望ましい方法であるか、否かについては、まったく別の問 題です。 以下の Perl sub Inc は、2 つの引数をとり、それぞれをインクリ メントします。 sub Inc { ++ $_[0] ; ++ $_[1] ; } そして、これを呼び出す C 関数です。 Perl manpages Last change: Release 5.0 Patchlevel 00 10 PERLCALL(1) USER COMMANDS PERLCALL(1) static void call_Inc(a, b) int a ; int b ; { dSP ; int count ; SV * sva ; SV * svb ; ENTER ; SAVETMPS; sva = sv_2mortal(newSViv(a)) ; svb = sv_2mortal(newSViv(b)) ; PUSHMARK(sp) ; XPUSHs(sva); XPUSHs(svb); PUTBACK ; count = perl_call_pv("Inc", G_DISCARD); if (count != 0) croak ("call_Inc : expected 0 return " "value from 'Inc', got %d\n", count) ; printf ("%d + 1 = %d\n", a, SvIV(sva)) ; printf ("%d + 1 = %d\n", b, SvIV(svb)) ; FREETMPS ; LEAVE ; } perl_call_pv からリターンした後で、スタック上にプッシュされ た 2 つのパラメータにアクセスするために、これらのアドレスを 記録しておく必要があります。 このため 2 つの変数 sva と svb を使っています。 これらの値を保持する Perl スタックのエリアは、perl_call_pv から制御が戻るときまでに、何ものかによって破壊されていること が十分に有り得るから、こういった操作が必要になるのです。 例 6: G_EVAL を使う 今度は G_EVAL を使う例です。 以下は、2 つの引数の差を計算す る Perl sub です。 結果が負になると、sub は die を呼びます。 sub Subtract { my ($a, $b) = @_ ; Perl manpages Last change: Release 5.0 Patchlevel 00 11 PERLCALL(1) USER COMMANDS PERLCALL(1) die "death can be fatal\n" if $a < $b ; $a - $b ; } これを呼ぶ C の方は、 static void call_Subtract(a, b) int a ; int b ; { dSP ; int count ; SV * sv ; ENTER ; SAVETMPS; PUSHMARK(sp) ; XPUSHs(sv_2mortal(newSViv(a))); XPUSHs(sv_2mortal(newSViv(b))); PUTBACK ; count = perl_call_pv("Subtract", G_EVAL|G_SCALAR); /* Check the eval first */ sv = GvSV(gv_fetchpv("@", TRUE, SVt_PV)); if (SvTRUE(sv)) printf ("Uh oh - %s\n", SvPV(sv, na)) ; SPAGAIN ; if (count != 1) croak ("call_Subtract : expected 1 return " "value from 'Subtract', got %d\n", count) ; printf ("%d - %d = %d\n", a, b, POPi) ; PUTBACK ; FREETMPS ; LEAVE ; } となります。 call_Subtract が call_Subtract(4, 5) のように呼ばれると、以下のように表示されます。 Uh oh - death can be fatal Perl manpages Last change: Release 5.0 Patchlevel 00 12 PERLCALL(1) USER COMMANDS PERLCALL(1) 注意点 1. die を捉えるために、G_EVAL フラグを使用しました。 この フラグを使用しないと、プログラムは途中終了してしまいま す。 2. C 関数の中の sv = GvSV(gv_fetchpv("@", TRUE, SVt_PV)); if (SvTRUE(sv)) printf ("Uh oh - %s\n", SvPVx(sv, na)) ; という部分は、Perl の書くところの print "Uh oh - $@\n" if $@ ; と同じことになります。 例 7: perl_call_sv を使う これまでの例では、Perl sub の名前を C から呼ばれるように扱っ てきました。 ですが、ときには Perl スクリプトの中から、Perl sub の名前を指定することができないと、困ることがあります。 sub fred { print "Hello there\n" ; } CallSub("fred") ; のような Perl コードを考えてみましょう。 CallSub を定義する XSUB の一部は、 void CallSub(name) char * name CODE: PUSHMARK(sp) ; perl_call_pv(name, G_DISCARD|G_NOARGS) ; のようになります。 今のところは、これで良いのかもしれません。 問題は、Perl sub が文字列でしか表現できないということです。 Perl 4 では、これで十分なのですが、Perl 5 では sub へのリフ ァレンスや無名の sub が許されています。 そういった場合に、 perl_call_sv が役に立つのです。 次の CallSub のコードは、先のものと同一ですが、引数 name を SV* で定義し、perl_call_pv の代わりに perl_call_sv を使って います。 Perl manpages Last change: Release 5.0 Patchlevel 00 13 PERLCALL(1) USER COMMANDS PERLCALL(1) void CallSub(name) SV* name CODE: PUSHMARK(sp) ; perl_call_sv(name, G_DISCARD|G_NOARGS) ; fred を呼ぶのに SV を使っていますから、Perl 側では、 CallSub("fred") ; Callsub(\&fred) ; $ref = \&fred ; CallSub($ref) ; CallSub( sub { print "Hello there\n" } ) ; といった記法が、すべて可能になります。 ご覧のように、perl_ call_sv を使えば、Perl sub をかなり柔軟に指定することができ るようになります。 例 8: perl_call_argv を使う 次にあげるのは、渡された引数を表示する Perl sub です。 sub PrintList { my(@list) = @_ ; foreach (@list) { print "$_\n" } } そして、PrintList を呼ぶ perl_call_argv の例です。 call_PrintList { dSP ; char * words[] = {"alpha", "beta", "gamma", "delta", NULL } ; perl_call_argv("PrintList", words, G_DISCARD) ; } 注目したいのは、この場合には、PUSHMARK を呼ぶ必要がないとい うことです。 perl_call_argv 側で自動的に行なうからです。 例 9: perl_call_method を使う [この節は執筆中] 以下のような Perl コードを考えてみましょう。 Perl manpages Last change: Release 5.0 Patchlevel 00 14 PERLCALL(1) USER COMMANDS PERLCALL(1) { package Mine ; sub new { bless [@_] } sub Display { print $_[0][1], "\n" } } $a = new Mine ('red', 'green', 'blue') ; call_Display($a, 'Display') ; メソッド Display は、単にリストの最初の要素を出力するもので す。 そして、call_Display の XSUB インプリメンテーションで す。 void call_Display(ref, method) SV * ref char * method CODE: PUSHMARK(sp); XPUSHs(ref); PUTBACK; perl_call_method(method, G_DISCARD) ; コンテキスト情報を蓄える方策 [この節は執筆中] コールバックを設計するときに克服すべき、陥りやすい問題の一つ は、C のコールバック関数と Perl の同等のものの間での対応を覚 えておく方法を見つけることです。 以下の例を考えてください。 .... 別のスタック操作 [この節は執筆中] Perl sub から返された値をアクセスするために、POP* マクロだけ を使ってきましたが、これらのマクロを使わずに、直接スタックを 読むこともできます。 以下のコードは .... SEE ALSO perlapi manpage、perlguts manpage、perlembed manpage Perl manpages Last change: Release 5.0 Patchlevel 00 15 PERLCALL(1) USER COMMANDS PERLCALL(1) AUTHOR Paul Marquess <pmarquess@bfsec.bt.co.uk> ドキュメントの作成に協力してくれた、次の方々に感謝します。 Jeff Okamoto, Tim Bunce. DATE Version 0.4, 17th October 1994 Perl manpages Last change: Release 5.0 Patchlevel 00 16