メメメモモ

プログラミング、筋トレ、ゲーム、etc

XSお勉強メモ1

XS/XSUBとは

  • PerlとC言語コードの拡張インタフェース記述用言語
  • PerlC言語のglue
  • C言語ですでに実装されているライブラリを使いたい時にXSを利用する

xsubppとは

  • XSのコンパイラ
  • XSで記述されたソースをコンパイルして、Cのソースを生成する
    • Hoge.xsからHoge.cを生成する
  • perlの型(スカラー、ハッシュなど)とCの型(int,charなど)のマッピング情報が記述されたtypemapファイルを読み込む

コンパイルの順番と読み込み

  • .xsファイル -> [xsubpp] -> .cファイル(Cマクロいっぱい) -> [Cプリプロセッサ] -> [Cコンパイラ] -> .bundleファイル
  • .pmファイルから「XSLoader::load」を使って、共有オブジェクトファイルを読み込む。


(.xsファイルから.soファイル(共有オブジェクトファイル)が生成されるらしいけど、見当たらない><)

コード

下記のコマンドでひな形を作成

h2xs -A -b 5.8.1 -n Foo::Bar


Bar.xsの中身。

// EXTERN.h perl.h XSUB.h の順番で書く
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

#include "ppport.h"

=pod
Cを書くエリア
=cut

MODULE = Foo::Bar               PACKAGE = Foo::Bar

=pod
XSエリア
=cut


lib/Foo/Bar.pmの中身。

package Foo::Bar;

use 5.008001;
use strict;
use warnings;

require Exporter;

our @ISA = qw(Exporter);
                                             
our %EXPORT_TAGS = ( 'all' => [ qw(                                                       
                                                                                         
) ] );

our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );

our @EXPORT = qw(                                                                         

);

our $VERSION = '0.01';

# 共有オブジェクトコードを読み込む
require XSLoader;
XSLoader::load('Foo::Bar', $VERSION);

1;

コンパイルしてみる

下記の流れでコンパイル。

perl Makefile.PL
make


コンパイル出力の流れ。

  • cp lib/Foo/Bar.pm blib/lib/Foo/Bar.pm
    • blib下にpmファイルをコピー
  • perl (Path)/ExtUtils/xsubpp -typemap (Path)/ExtUtils/typemap Bar.xs > Bar.xsc && mv Bar.xsc Bar.c
    • xsubppでxsファイルをコンパイル
    • -typemapオプションでtypemapファイルを読み込み
    • Bar.cファイルが生成される
  • cc -c (なんか色々オプション) Bar.c
  • cc -bundle -undefined dynamic_lookup Bar.o -o blib/arch/auto/Foo/Bar/Bar.bundle

デバッガでたどってみる

pmファイルの「XSLoader::load('Foo::Bar', $VERSION);」の直前に「$DB::single=1」を追加してコンパイル。
下記のコマンドで実行。

perl -d -Mblib -MFoo::Bar -e ''

シングルステップ(sを入力)で進める。


Bar.bundleを読みこんでいるような部分を見つける。これが共有オブジェクトコード?