理系学生日記

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

perlxs を読みつつ strlen を Perl から呼び出してみた

perlxstut を読んでみたのはいいんだけど,まだ何かできる気がしない.
結果として perlxs を読んだ方が良い気がしてきたので,読みはじめたところ.
で,何か作ってみるかということで,perlxs を読み進めつつ,C の str 系関数を呼び出せるようにする.実用上,何の意味もないけど!!

作ってみるどー!

h2xs -A -n String

を実行すると,関連ファイルと一緒に以下のような String.xs が生成される.

#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

#include "ppport.h"


MODULE = String         PACKAGE = String

ではでは,XSUB を書いてみませう.
一番シンプルな XSUB は以下の 3 つで構成されます.

  • 返り値についての記述
  • XSUB の名前
  • 引数に関する記述

それに,C の strlen 呼び出しを含めて,strlen はこんな感じに記述できそうです.んじゃ,これを String.xs に追記してみよう.引数の型が括弧内にないのは,昔の C 言語っぽいですね.

size_t
strlen(s)
        const char* s
    CODE:
        RETVAL = strlen(s);
    OUTPUT:
        RETVAL

関数名と返り値は,異なる行かつ左寄せで記述しないといけないようです.だからこんなのはダメ.だって同じ行にあるもんね.

size_t strlen(s)
(略)

というわけで,XSUB では,最初の 2 行で必ず

  1. XSUB の返り値
  2. XSUB の名前とその引数

を記述する形になります.
でも実は,同じ行にあっても動いちゃうんだ…!!よくわからないけど!!とりあえず非推奨ってことでいいのかな.

ちなみに,書き方を変えて,こういう風にしても動きます.引数の型情報を,現代の C っぽく括弧内に含める形.

size_t
strlen( const char * s )
    CODE:
        RETVAL = strlen(s);
    OUTPUT:
        RETVAL


それ以後の行はどうなるかというと,XXX: というようなラベル的なものがない場合は,全部 INPUT: のセクションとして扱われ,INPUT: セクションは次に XXX: の形のものが来るまでの範囲となります.

とりあえず使ってみましょうか!

t/String.t にこんなの書く.

use Test::More tests => 3;
BEGIN { use_ok('String') };
is( String::strlen( "aaaaa" ), 5, "length of aaaaa");
is( String::strlen( "kiririmode" ), 10, "length of kiririmode");

んじゃ,テストしよう.

[y-kiri String 05:44:45 ] make test
PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(0, 'blib/lib', 'blib/arch')" t/*.t
t/String......ok
All tests successful.
Files=1, Tests=3,  0 wallclock secs ( 0.01 usr  0.00 sys +  0.02 cusr  0.01 csys =  0.04 CPU)
Result: PASS

ってことで,strlen はうまく呼び出せたみたいです!