とりあえずXSに触れてみる。モダンPerl入門を読みながら
xsに触れたことがないのでモダンPerl入門の8.2を読みながらとりあえず作ってみた。
本に書いてあることをほぼ丸コピーして、
package MyApp::Double sub calc_double { my $x = shift; $x * 2; }
と同じ動きをするモジュールを作り、
perl Makefile.PL
make
make test
がうまくいったら「やったー」で今日は終わり。
module-setupを使ってひな形作り
本の中ではExtUtils::MakeMakerというのを使ってひな形を作ってたのですけど、
色々試したかったのでmodule-setupを使ってみました。
module-setupについてはModule::Setup でらくらくモジュール作成 - JPerl Advent Calendar 2009
上のページにある通り、
module-setup --init --flavor-class=XS xs
でxsのひな形を作り、
module-setup MyApp::Double
をやってみたんですが、
Double.xs:7:20: error: ppport.h: No such file or directory
というエラーが出てしまって僕の理解を超えたので断念。
(ppport.hをローカルに作らないといけないのかな?)
なので、XSモジュール用のModule::Setupのflavorを作った - Clouder::BloggerからXSFlavor.pmを持ってきてxsのflavorにしました。
cat >> XSFlavor.pm # (ページからコピペしたもの) module-setup --init --flavor-class=+XSFlavor xs module-setup MyApp::Double xs
で、MyApp-Doubleというディレクトリが作成される。
Double.xsの修正
ひな形が作成された時点で
% grep XSLoader::load lib/MyApp/Double.pm XSLoader::load(__PACKAGE__, $VERSION);
という感じで.soファイルを読み込むためのコードが書かれているようなので、
Double.xsにcalc_doubleを追記するだけの作業。
行末に
int calc_double(sv) SV *sv; PREINIT: int x; CODE: x = SvIV(sv); RETVAL = x * 2; OUTPUT: RETVAL
を加えるだけ。
テストコードの作成
あとはテストコード。
t/00_compile.tでuse_okのテストをしてあるので、
% cat >> t/01_basic.t use strict; use Test::More; use MyApp::Double; my @list = (-100, 41, 3, 0, 50, 81, 100); for my $x (@list) { is(MyApp::Double::calc_double($x), $x * 2, "$x + 2 = " . ($x * 2)); } done_testing;
で完了。
結果
% perl Makefile.PL include /Users/monmon/Documents/perl/xs/MyApp-Double/inc/Module/Install.pm include inc/Module/Install/Metadata.pm include inc/Module/Install/Base.pm Cannot determine perl version info from lib/MyApp/Double.pm include inc/Module/Install/AuthorTests.pm include inc/Module/Install/Compiler.pm include inc/Module/Install/Makefile.pm include inc/Module/Install/Can.pm include inc/Module/Install/TestBase.pm include inc/Module/Install/Include.pm include inc/Test/Base.pm include inc/Test/Base/Filter.pm include inc/Spiffy.pm include inc/Test/More.pm include inc/Test/Builder.pm include inc/Test/Builder/Module.pm include inc/Module/Install/WriteAll.pm include inc/Module/Install/Win32.pm include inc/Module/Install/Fetch.pm Writing Makefile for MyApp::Double Writing META.yml % make cp lib/MyApp/Double.pm blib/lib/MyApp/Double.pm /usr/local/bin/perl "-Iinc" /usr/local/lib/perl5/5.10.1/ExtUtils/xsubpp -typemap /usr/local/lib/perl5/5.10.1/ExtUtils/typemap -typemap typemap -typemap typemap Double.xs > Double.xsc && mv Double.xsc Double.c Please specify prototyping behavior for Double.xs (see perlxs manual) cc -c -I. -fno-common -DPERL_DARWIN -no-cpp-precomp -DDEBUGGING -fno-strict-aliasing -pipe -fstack-protector -I/opt/local/include -O3 -g -DVERSION=\"0.01\" -DXS_VERSION=\"0.01\" "-I/usr/local/lib/perl5/5.10.1/darwin-2level/CORE" Double.c Running Mkbootstrap for MyApp::Double () chmod 644 Double.bs rm -f blib/arch/auto/MyApp/Double/Double.bundle env MACOSX_DEPLOYMENT_TARGET=10.3 cc -bundle -undefined dynamic_lookup -L/usr/local/lib -L/opt/local/lib -fstack-protector Double.o -o blib/arch/auto/MyApp/Double/Double.bundle \ \ chmod 755 blib/arch/auto/MyApp/Double/Double.bundle cp Double.bs blib/arch/auto/MyApp/Double/Double.bs chmod 644 blib/arch/auto/MyApp/Double/Double.bs Manifying blib/man3/MyApp::Double.3 % make test [~/Documents/perl/xs/MyApp-Double] PERL_DL_NONLAZY=1 /usr/local/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(0, 'inc', 'blib/lib', 'blib/arch')" t/*.t xt/*.t t/00_compile.t ...... ok t/01_basic.t ........ ok xt/01_podspell.t .... skipped: Test::Spelling is not installed. xt/02_perlcritic.t .. skipped: Test::Perl::Critic is not installed. xt/03_pod.t ......... ok All tests successful. Files=5, Tests=9, 0 wallclock secs ( 0.05 usr 0.03 sys + 0.19 cusr 0.05 csys = 0.32 CPU) Result: PASS
問題なく上手くいったので終了。