Perl入門ゼミ

テキスト処理、Linuxサーバー管理、Web開発ならPerl
  1. Perl
  2. XS
  3. here

複数モジュールを使うXSの簡単な実装方法

XSを使ってモジュールを作ろうとしたときに、複数のモジュールに分割するときにふと困りました。たとえば、SomeModuleとSomeModule::Utilの両方でXSの実装を行いたい場合です。方法を調べていたのですが、実装方法が結構煩雑で難しいなと感じました。

いろいろと試していたのですが、次の方法が簡単なように思えたので紹介しておきます。この方法の利点は、次のとおりです。

  1. Makefile.PLを修正する必要がない
  2. SomeModule.xsというファイルの名前を修正する必要がない
  3. SomeModule.xsという一枚のXSファイルだけでOK
  4. 標準ツールのh2xsでも大丈夫

h2xsでモジュールを作成

最初にh2xsでXS用のモジュールを作成します。

h2xs -A -n SomeModule

こうすると「SomeModule」というディレクトリが作成されます。次のようなファイルとディレクトリが作成されます。

Changes
lib/
Makefile.PL
MANIFEST
ppport.h
README
SomeModule.xs
t/

XSファイルの記述

XSファイルを作成していきます。「foo」と表示するfooという関数をSomeModuleに追加、「bar」と表示するbarという関数をSomeModule::Utilに追加してみます。

まず最初にXSファイルを開くと次のようになっていると思います。

#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

#include "ppport.h"


MODULE = SomeModule		PACKAGE = SomeModule		

まず覚えてほしいことは、「MODULE = SomeModule PACKAGE = SomeModule」のセクションは一番下側に置く必要があるということです。この部分を最後においておかないとXSのロードに失敗してしまいます。

では記述しましょう。「MODULE = SomeModule::Util PACKAGE = SomeModule::Util」を追加します。そしてXSでbarを定義します。また「MODULE = SomeModule PACKAGE = SomeModule」のセクションに、fooを定義します。

#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

#include "ppport.h"

MODULE = SomeModule::Util PACKAGE = SomeModule::Util

void
bar(...)
  PPCODE:
{
  PerlIO_printf(PerlIO_stdout(), "bar\n");
  XSRETURN(0);
}

MODULE = SomeModule		PACKAGE = SomeModule		

void
foo(...)
  PPCODE:
{
  PerlIO_printf(PerlIO_stdout(), "foo\n");
  XSRETURN(0);
}	

モジュールの作成

ここまでできれば、SomeModuleとSomeModule::Utilを作成するだけです。

SomeModuleのソースコード

SomeModule.pmのソースコードは最初のままでもかまいません。少し整理して以下のようにしました。

package SomeModule;

use strict;
use warnings;

our $VERSION = '0.01';

require XSLoader;
XSLoader::load('SomeModule', $VERSION);

1;

SomeModule::Utilのソースコード

SomeModule::Util::barも作ってみましょう。これは「lib/SomeModule/Util.pm」に保存してください。これはパッケージ名だけが宣言されたほとんど空のファイルです。

package SomeModule::Util;

1;

テストスクリプト

テストスクリプトを作成します。これは、XSファイルがあるディレクトリと同じディレクトリにおいてください。

use strict;
use warnings;

use SomeModule;
use SomeModule::Util;

SomeModule::foo();
SomeModule::Util::bar();

コンパイルして実行

コンパイルして実行してみましょう。

perl Makefile.PL
make
perl -Mblib test.pl

次のように出力されれば成功です。

foo
bar

XSを複数モジュールで記述するのは、それほど難しくなさそうですね。

  • Perlとはテキスト処理の記述性とパフォーマンスに優れ、正規表現が言語に組み込まれているプログラミング言語です。
  • Linuxサーバーでのフィルタリングプログラム、複数行の文字列を処理、ファイル内容の検索・置換などが得意
  • Perlはgitopensslなど広く普及したUnix/Linuxミドルウェアの補助ツールとして採用実績あり。後方互換性とポータビリティの高さがひとつの理由と推測。
  • 大量のテキストを扱うWeb開発も得意。ロングテールSEOを意識したWebサイト、アドテクやソーシャルゲームでの50ms以内のJSONの生成など。