XS入門でやった事メモ

h2xsコマンド

h2xsコマンドでひな形を作成します。

$ h2xs -A -n MyTest

コンパイル

出来上がったディレクトリに移動して次のコマンドを実行します。

$ perl Makefile.PL
$ make

Hello World!を表示する関数

XSでHello World!を表示するプログラムを書きます。
「MyTest.xs」というファイルがあります。
このファイルの一番下に、次のようにコードを追加します。

#include "perl.h"
#include "XSUB.h"
#include "ppport.h"
MODULE = MyTest                PACKAGE = MyTest

void
hello()
CODE:  
 PerlIO_stdoutf("Hello, world!\n");


makeコマンドでコンパイルして、下記のコマンドで動作確認を行ないます。

$ perl -Mblib -MMyTest -e "MyTest::hello()"
Hello, world!

二つの数値を足し算する関数

XSで二つの数値を受け取って足し算するプログラムを書きます。
先ほどと同じように「MyTest.xs」というファイルにコードを追加します。

int
plus(a,b)
int a
int b
PREINIT:
  int sum;
CODE:  
  sum = a + b;  
  RETVAL = sum;
OUTPUT:
  RETVAL


makeコマンドでコンパイルして、下記のコマンドで動作確認を行ないます。

$ perl -Mblib -MMyTest2 -e "print MyTest2::plus(1,2)"
3

Cで定義されている関数にマッピング

C言語ですでに実装されている関数にマッピングする機能を用います。
下記のような台形形式で積分するCプログラムをマッピングする場合を試しました。

// trapezoidal.h

double f(double x) {
    return x * x;
}

double trapezoidal(int N, double a, double b) {
    int i;
    double x[10000];
    double y[10000];
    double h;
    double S = 0.0;

    if (N >= 10000) {
        return -1;
    }

    h = (b-a)/N;
    for (i = 0; i <= N; i++) {
        x[i] = a + i*h;
    }

    for (i = 0; i <= N; i++) {
        y[i] = f(x[i]);
        y[i+1] = f(x[i+1]);
        S = S + h*(y[i] + y[i+1])/2.0;
    }

    return S;
}


MyTest.xsでは、trapezoidal関数の引数と返す型を合わせて記述すれば「CODE:」を書く必要はありません。

double
trapezoidal(N,a,b)
int Ndouble a
double b


コンパイルをして、下記のコマンドで動作確認をします。

$ perl -Mblib -MMyTest -e "print MyTest::trapezoidal(2000,0,3)"
9.006751125

メモ

XSはperl内部を覗き込むときの入り口としていいかもしれない。
ただ実際に使用する場面は、普通はなさそう。
使うとしても必要最低限のマッピングを行なうぐらい。
うんこプログラマがXSを書いたら危険だから書くな、って偉い人が言ってた。
だから実用でXSプログラムを書く事はないだろうなぁ。

参考

モダンPerl入門 (CodeZine BOOKS)

モダンPerl入門 (CodeZine BOOKS)