Inline::Cで学ぶperlguts(その4)

最近、カオスCGの計算をしてるんだけど、そろそろCで書き直すフェーズなので、
なんとかInline::Cで解決できないかと思って、
今回は、配列リファレンスを返す方法を学んでみようと思う。

use v5.14;
use strict;
use warnings;

use Data::Dumper;

use Inline C => q{
    SV * create_array_reference(SV *sv)
    {
        const IV n = SvIV( sv );
        if ( n < 0 ) {
            return &PL_sv_undef;
        }
        else {
            AV *array = newAV();
            for (IV i=0; i<n; i++) {
                av_push( array, newSViv(i) );
            }

            return newRV_noinc( (SV *)array );
        }
    }
};

foreach ( 0, -1, 2 ) {
    my $foo = create_array_reference( $_ );
    if ( defined $foo ) {
        say Dumper($foo);
    }
    else {
        say 'undef!';
    }
}

$ perl aaa.pl
$VAR1 = [];

undef!
$VAR1 = [
0,
1
];

整数はintでも良いのかなーって思いながらも、
とりあえず、IVを使ってみた。
I32とかの方が良いんですかね?

あと、戻り値の型がAV *だと、
&PL_sv_undefを返してもdefinedで思ったように判定できなくて、
それで戻り値の型をSV *に変更して、
newRV_incを使って配列リファレンスを返すようにした。
これなら、&PL_sv_undefを返してもdefinedで判定できた。

undefを返したい場合は、この辺を気にしないとダメっぽいですね。

追記 2016/02/09
newRV_noincでなければならないところで、newRV_incを使っていたので修正。
newRV_incで、引数の参照カウンタを余分にインクリメントしてた。

XSでメモリークを避けるたった一つの方法 – Islands in the byte stream
http://d.hatena.ne.jp/gfx/20100519/1274247355

次回は、こちらを参考にsv_2mortalを使ってみようと思う。
— ここまで追記 —

おしまい。

Leave a Comment