さて、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 ; }
注意点は、
G_SCALAR
だけを使用しています。これは、
@_ 配列が作られ、 `Adder' からの返された値は、
perl_call_pv
の呼び出し後も存在することを表わします。
G_DISCARD
を
指定することはできません。つまり、自分で Perl スタックをきちんと整理して、
一時的な値も廃棄する必要があります。これが、関数の最初で、
ENTER ; SAVETMPS ;として、最後に
FREETMPS ; LEAVE ;としていることの目的です。 `ENTER'/ `SAVETMPS' のペアが、使用 する一時的な領域を作ります。逆にいうと、自分で廃棄できるものは、これらを 呼び出した後に作ったものに限定されるということです。 `FREETMPS' / `LEAVE' のペアは、Perl sub が返した値を捨て、生成 した `SV' について、解放直前の情報をダンプします。コードの最初に `ENTER' / `SAVETMPS ' をおくことで、それ以上の開放情報が壊され るのを防ぎます。
SPAGAIN
マクロの目的は、ローカルなスタックポインタをリフレッシュ
することです。 perl_call_pv
の呼び出しの間に再配置された Perl ス
タックへメモリ配置を行なうことができますから、これが必要になります。
コードの中で Perl スタックポインタを利用する場合には、perl_call_*
関数や他の Perl の内部関数を利用するときには必ず、 SPAGAIN
を使っ
てローカルなポインタをリフレッシュしなくてはなりません。
perl_call_pv
からの返却値をチェックするのが良いでしょう。
単一の値を期待するのは、一つであることを知っていることとは違います。誰か
が `Adder' を改造して、リストを返すようにし、その可能性をチェックし
ていなかったときに、この操作を行なってしまうと、Perl スタックの状態は、
矛盾したものになってしまいます。こんなことは、誰も望みはしないでしょう。
POPi
マクロを使用
しています。ここでは整数が必要であったため、POPi
を使用したのです。
返された値の型に応じて、以下の POP
マクロを使用することができます。
POPs SV POPp ポインタ POPn 倍精度 POPi 整数 POPl long 整数
PUTBACK
は、関数を抜ける前に、Perl スタックを矛盾の無い状
態にしておくために使用しています。これは、POPi
でスタックから返却
値を取り出したときに、ローカルなスタックポインタのみを更新するため、必要
となります。先の例で説明したように PUTBACK
は、グローバルなスタッ
クポインタをローカルなスタックポインタの値にあわせるように設定します。
Go to the first, previous, next, last section, table of contents.