C で一番直感的に階乗を再帰で書き下すとこんな感じで,
#include <stdio.h> int factorial(int n) { return (n > 0)? n * factorial(n-1) : 1; } int main() { printf("%d!=%d\n", 5, factorial(5)); return 0; }
もちろん実行結果は正しい.
[y-kiri Fact 03:32:48 ] ./factorial 5!=120
ところが,XS でこれを実現しようとすると,なんかおかしい.
Fact.xs
#include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include "ppport.h" MODULE = Fact PACKAGE = Fact int factorial(n) int n CODE: RETVAL = (n > 0)? n * factorial(n - 1) : 1; OUTPUT: RETVAL
上の Fact.xs を使うテストスクリプトがこれ.
# 敢えて今は testlib 使ってる.
use Test::More tests => 4; BEGIN { use_ok('ExtUtils::testlib'); use_ok('Fact'); }; is( Fact::factorial(0), 1, "0!"); is( Fact::factorial(1), 1, "1!");
出力.
[y-kiri Fact 03:37:09 ] perl test.pl 1..4 ok 1 - use ExtUtils::testlib; ok 2 - use Fact; ok 3 - 0! dyld: lazy symbol binding failed: Symbol not found: _factorial Referenced from: /Users/ykiri/test/xs/Fact/blib/arch/auto/Fact/Fact.bundle Expected in: dynamic lookup dyld: Symbol not found: _factorial Referenced from: /Users/ykiri/test/xs/Fact/blib/arch/auto/Fact/Fact.bundle Expected in: dynamic lookup Trace/BPT trap
再帰呼び出し時に,まだ factorial のシンボル名が見つけられていないように見える.
perlxstut 途中までしか読んでないのに,再帰しようとしたのがマズいのかなー.これからどうやって再帰できるか,分かるようになるかなー.