Go to the first, previous, next, last section, table of contents.


例 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 ;
}

注意点は、

  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 マクロを使用 しています。ここでは整数が必要であったため、POPi を使用したのです。 返された値の型に応じて、以下の POP マクロを使用することができます。
    POPs    SV
    POPp    ポインタ
    POPn    倍精度
    POPi    整数
    POPl    long 整数
    
  6. 最後の PUTBACK は、関数を抜ける前に、Perl スタックを矛盾の無い状 態にしておくために使用しています。これは、POPi でスタックから返却 値を取り出したときに、ローカルなスタックポインタのみを更新するため、必要 となります。先の例で説明したように PUTBACK は、グローバルなスタッ クポインタをローカルなスタックポインタの値にあわせるように設定します。


Go to the first, previous, next, last section, table of contents.

検索式: