拡張ライブラリチュートリアルをやってみる#4

ラッパーをいちいち手書きすると大変なので,Swig を使うやり方.

##下準備 Swig 自体のインストール

% sudo apt-get install swig

##整数の足し算 最初にやった例を,Swig でやってみる.

まずは Swig の入力ファイルから1

  • test5.i
%module test
%{
%}

extern int add(int a, int b);

これは,

  • test モジュールを作成する
  • 外部参照する関数 add を使う

ということを宣言しているらしい.そしてこれを使ってラッパーを作成

% swig -ruby test5.i

作成されたファイルは test5_wrap.c で,中身は省略. ||<

Ruby の拡張ライブラリなので,extconf.rb を作成する.

  • extconf.rb
require 'mkmf'
create_makefile('test')

これは最初にやった例と同じ.そしてコンパイル.

% ruby extconf.rb
% make
% ruby -r'test' -e'p Test.add(1, 2)'
3

確かに記載しなくていいのは楽ではあるが,中身的に何やってるかわからないのが,ちょっとあれな感じかな.

##NArray での要素の掛け算 NArrayを使った例を Swig で.

同じく Swig の入力ファイルから.

  • test6.i
%module test
%{
#include "narray.h"
%}

%typemap(ruby,in) (float *NARRAY, int LENGTH){
  VALUE na;
  struct NARRAY *n_na;

  na = na_cast_object($input, NA_SFLOAT);
  GetNArray(na, n_na);
  $1 = (float*)n_na->ptr;
  $2 = n_na->total;
}

extern float mul_all(float *NARRAY, int LENGTH);

そしてラッパーの作成とコンパイル,実行.

% swig -ruby test6.i
% make
% irb
>> require 'narray'
=> true
>> require 'test'
=> true
>> Test.mul_all(NArray.sfloat(5).indgen!(1,1))
=> 21.0

ん?なぜか答えが合わない.Swig で生成されたラッパーを見ると,どうも mul_all の関数プロトタイプ宣言がない模様.なので,narray.h を include している後に,それを書いておく.

  • test6.i
%module test
%{
#include "narray.h"
float mul_all(float *array, int nx);
%}

%typemap(ruby,in) (float *NARRAY, int LENGTH){
  VALUE na;
  struct NARRAY *n_na;

  na = na_cast_object($input, NA_SFLOAT);
  GetNArray(na, n_na);
  $1 = (float*)n_na->ptr;
  $2 = n_na->total;
}

extern float mul_all(float *NARRAY, int LENGTH);

再度,ラッパーの作成とコンパイル,実行.

% swig -ruby test6.i
% make
% irb
>> require 'narray'
=> true
>> require 'test'
=> true
>> Test.mul_all(NArray.sfloat(5).indgen!(1,1))
=> 120.0

ようやく成功.これがわかるのにちょっと時間かかりました.C は難しいなぁ.

あと,やはり Swig の部分がわからない.調べるのもいいが,ひとまずは自力で書いてみることにしよう.


  1. emacs で対応する mode がないのかな?知っている人がいたら教えてください. [return]
 
comments powered by Disqus