理系学生日記

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

XS で階乗の計算ができない

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 途中までしか読んでないのに,再帰しようとしたのがマズいのかなー.これからどうやって再帰できるか,分かるようになるかなー.