Perl - XSでDLLを呼び出す(その2)

前回の続きとして、作成したExample1モジュールを使って見る。

インストールする前に使用する

以下のスクリプトを "c:\xs\Example1\TestEx1.pl" として保存する。

use ExtUtils::testlib; # @INCにblib\archとblib\libを追加する
use Example1;

print TEST_CONST_123 . "\n";
print TEST_CONST_456 . "\n";
print TEST_CONST_PI . "\n";
print TEST_CONST_HW . "\n";

インストールする前のモジュールを使用するためには、@INC変数にそのモジュールのパスを登録しなければならない。
ExtUtils::testlibによってそれが実現される。
上記のスクリプトを実行すると以下の結果となる。

123
456
3
TEST_CONST_HW

おや?TEST_CONST_PIが整数部だけになってしまっている。
TEST_CONST_HWに至っては内容が定義されていないために、"\n" と連結されたことでそのままの文字列になってしまった。
どうやら、小数定数は整数に変換され、文字列定数は無視されるようだ。
そう言えば、ビルド時に「const-c.inc(55) : warning C4244: '=' : 'const double' から 'long' に変換しました。データが失われているかもしれません。」と警告メッセージが表示されていた。
調査した結果、この問題を解決するためにはMakefile.plとlib\Example1.pmを変更するのが一番良い手段のようだ。
Makefile.plは以下のように変更する。

  my @names = (qw(TEST_CONST_123 TEST_CONST_456 TEST_CONST_PI));
                              ↓
  my @names = (qw(TEST_CONST_123 TEST_CONST_456),
               {name => "TEST_CONST_PI", type => "NV"},
               {name => "TEST_CONST_HW", type => "PV"});

この変更が必要な理由は、@namesに定義する定数のタイプを指定しない場合、デフォルトではIVになるように、上記記述直後の以下の記述でDEFAULT_TYPEを指定しているからである。

  ExtUtils::Constant::WriteConstants(
                                     NAME         => 'Example1',
                                     NAMES        => \@names,
                                     DEFAULT_TYPE => 'IV',
                                     C_FILE       => 'const-c.inc',
                                     XS_FILE      => 'const-xs.inc',
                                  );


ついでに定数のタイプを以下にまとめて置こう。

名前 意味 説明
IV Integer Value 整数値
NV Number Value 実数値
PV Pointer Value 文字列(SVがScalar Valueなので代用か?)


lib\Example1.pmには以下のようにTEST_CONST_HWの記述を追加する。

our %EXPORT_TAGS = ( 'all' => [ qw(
        TEST_CONST_123
        TEST_CONST_456
        TEST_CONST_PI
        TEST_CONST_HW   #←追加
) ] );
our @EXPORT = qw(
        TEST_CONST_123
        TEST_CONST_456
        TEST_CONST_PI
        TEST_CONST_HW   #←追加
);
=head2 Exportable constants

  TEST_CONST_123
  TEST_CONST_456
  TEST_CONST_PI
  TEST_CONST_HW

上記の追加を行わないと、TEST_CONST_HWの定義が無いので、その定数を使用することが出来ない。
ただし、最後のhead2はドキュメントに出力される内容なので無くても動作する。
どうやら、ActivePerl 5.8.7付属のh2xsコマンドでは小数や文字列を扱えないようだ。
それではもう一度ビルドとテストをして見よう。

> nmake clean
> perl Makefile.pl
> nmake
> perl TestEx1.pl

これで各定数の内容が正しく表示されたはずである。

次回は簡単なサブルーチンを定義するコードを記述してみようと思う。