理系学生日記

おまえはいつまで学生気分なのか

PPCODE と CODE の違い

Perl XS でちょっと複雑なことをしようと思うと、CODE または PPCODE セクションに C レベルのコードを記述する必要がありますが、この CODE と PPCODE セクションの違いはなんだろうということで調べてみました。詳細は perlxs の "The PPCODE: Keyword" や "The RETVAL Variable" を参照のこと。

CODE セクションと PPCODE セクションは両立できないことを前提としていますが、CODE セクションを用いると Perl のスタックポインタ (SP) が裏で自動的に設定されるようです。

In CODE: sections SP preserves the value which was on entry to the XSUB: SP is on the function pointer (which follows the last parameter).

おそらくスタックは以下のような形になっている。

  • XSUB のエントリーポイント <= SP
  • XSUB への n 番目の引数
  • XSUB への n-1 番目の引数
  • XSUB への n-2 番目の引数

・・・

  • XSUB への最初の引数

XSUB から制御が戻ると、普通は「XSUB への最初の引数」の領域にある値が戻り値として返ります。実際に CODE セクションを使う限りは SP を特に意識する必要はなく、"「XSUB への最初の引数」の領域" は RETVAL が自動的に使う形になっているようです。

CODE セクションとは逆に、PPCODE セクションを用いた場合は SP を強く意識しないといけません。

In PPCODE: sections SP is moved backward to the beginning of the parameter list, which allows ""PUSH*()"" macros to place output values in the place Perl expects them to be when the XSUB returns back to Perl.

PPCODE セクションを用いた場合は、SP が XSUB への最初の引数が置かれたコールスタック上の領域を指すことになります。

  • XSUB のエントリーポイント
  • XSUB への n 番目の引数
  • XSUB への n-1 番目の引数
  • XSUB への n-2 番目の引数

・・・

  • XSUB への最初の引数 <= SP

XPUSH* などを明示的に呼ぶというような SP の面倒な操作が必要な代わりに、複数の戻り値を XSUB から返せるようになります。