夜空日和 [出張版]

星を見上げながら、今日を語ってみようか

 

スポンサーサイト


Category: スポンサー広告   Tags: ---
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

SWIG で PPL を Ruby に部分移植してみた part.1


Category: 技術   Tags: ---
1. ヘッダーファイルからの移植開始

SWIGから移植するには、移植するライブラリでコンパイル可能でなければなりません。
つまり、ヘッダーファイルが必要になる訳ですが・・・

逆を言ってしまえば、インターフェイスが分かっていれば、自作ヘッダーでも問題ありません。

今回はPPLの移植ですが、PPLのヘッダーを直接使用していません。
理由は、後で述べます。



1.1 ヘッダーファイルを直接使用しない理由

ヘッダーファイルを直接使用しない理由として、2つの理由があります。

1 ). 外部定義が解決されない
2 ). ヘッダーに書かれている定義、全てが移植対象になってしまう。

たとえば、ppl.hh の場合、次の定義があります。
#if UCHAR_MAX == 0xff
#define CHAR_BITS 8
#else
#error "Unexpected max for unsigned char"
#endif
UCHAR_MAX は climits で定義されており、ラッパー作成時には未定義として扱われてしまいます。
なぜならば、SWIGでは #include ディレクティブは無視されてしまうからです。
これについては、SWIGのオプションで -includeall を指定することで解決できます。
ただし、機種依存定義については、解決されない場合があるようです。

また、SWIGの性質として、ヘッダーに書かれた定義「全て」を移植対象にしてしまう問題があります。
なので、#include を全て展開して出来たラッパーファイルは、とても巨大な物になってしまいます。

%ignore などで対象外にすることも可能ですが。
個人的には、「必要な物だけを定義する」ということをお勧めします。



1.2 ヘッダーファイルから、必要な部分を抽出する
ということで、 ppl.hh から必要な部分飲みを抽出したファイル ppl.partial.define.hpp を作りたいと思います。
/* Variable の必要な部分のみ */
class Variable {
public:
  explicit Variable(dimension_type i);

  dimension_type id() const;

  static dimension_type max_space_dimension();

  dimension_type space_dimension() const;

  memory_size_type total_memory_in_bytes() const;

  memory_size_type external_memory_in_bytes() const;

  bool OK() const;
};
ここで、注意として 「dimension_type」 や 「memory_size_type」 も変換対象になります。
そのため、特定の数値型として扱いたい場合は、 #define や typedef をしてください。
( 今回の場合は、何もしなくても数値型と演算できてるので、問題ないかもしれません )



1.3 インターフェイスファイルを作成する
では、SWIG用インターフェイスファイル ppl.i を作成したいと思います。
%module PPL
%{
  #include <ppl.hh>
  using namespace Parma_Polyhedra_Library;
%}

%include "ppl.partial.define.hpp"
これだけです。

%module は変換後のクラスを包むモジュール名を指定します。

%{ ~ %} の中は変換対象になりません。これは変換後のラッパーファイルに記述されることになります。
つまり、ラッパーファイルをコンパイルするために必要な情報ということです。
SWIG (version 2.0.5) では namespace の解決が上手くいかなかったので using してあります。

%include では、インターフェイスファイルに展開するファイルを指定します。
ここでは、 ppl.partial.define.hpp がここにベタ~と展開されます。

展開後、定義されているクラスなどから情報を抽出して、変換が始まります。
変換後には、 module_wrap.cxx (自分の場合は ppl_wrap.cxx) というファイルが作成されます。



1.4 変換 → コンパイル
では、ファイルが出来たので、実際に変換からコンパイルまでやってしまいたいと思います。
その前に、ruby用にコンパイルする場合は、extconf.rb を作っておきます。
(詳細は、extconf.rb のマニュアルを参照してください)
require 'mkmf'
$libs = "-l ppl"
create_makefile('PPL')
あとは、次のコマンドでぺぺぺっと作ります。
$ swig -c++ -ruby ppl.i
$ ruby extconf.rb
$ make -f Makefile
1つ目がSWIGでラッパーファイルを作成するところ。
2つ目がruby用のMakefileを作成するところ。
3つ目がMakefileでラッパーファイルをコンパイルするところです。

コンパイルに成功すると、 PPL.so という共有ライブラリが作成されます。
これをrubyで使用する場合は、次のように扱います。
require_relative 'PPL'

x = PPL::Variable.new(1)
p x.id  # => 1
お疲れ様です。
これであなたも、SWIGでラッパーを作成できます!
次からは、私が引っかかったことの紹介です。

スポンサーサイト


Comments

Leave a Comment



08 2017
SUN MON TUE WED THU FRI SAT
- - 1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31 - -

07

09


 
プロフィール

ひでたそ

Author:ひでたそ
Comment:
現役大学生で天文好き。
今日もどこかで、上を見ながら歩いています。

 
 
 
最新トラックバック
 
 
検索フォーム
 
 
 
ブロとも申請フォーム
 
QRコード
QRコード
 

Archive   RSS   Login

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。