夜空日和 [出張版]

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

 

スポンサーサイト


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

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


Category: 技術   Tags: ---
3. template は必要?

SWIGの問題点として、C++のtemplateがあると変換できないという問題があります。
これはマクロと同じ原因で、プロプロセッサを通さないと解決出来ないからです。

そのため、templateがある関数を使用する場合は、templateを隠すか、手動で解決する必要があります。
今回は、STL の std::vector を例に挙げます。



3.1. RubyでArrayを返したい

SWIGを使っていて思うのは、ArrayやHashを受け取る/返す関数を作成したい場合は、どうするのか?という点です。
SWIGでは、std::vector/std::mapを使用すると、自動でマッピングしてくれるそうです。
( std::map は試していないので、分かりません )

しかし、1つ問題があります。
それは 「SWIGは、template解決が行えない」 という問題です。



3.2. std::vector の解決

親切なことに、SWIGでは std::vector のインターフェイスファイルが用意されてます。
また、SWIGでは手動でtemplateを解決する (別の名前にマッピングする) 機構も用意されてます。
/* ppl.i */

%ignore std::vector::vector(size_type t);
%ignore std::vector::resize(size_type t);

%include "std_vector.i"

%template(VectorConstraint) std::vector<Constraint>;

std::vectorのインターフェイスファイルが std_vector.i です。
また、std::vector<Constraint> に VectorConstraint という名前を付けてテンプレート解決しています。
これは、単純に typedef をしているように感じます。
無くても Array クラスにマッピングされるんで、必要性は薄い気がします (^_^; )

ここで、ignoreが設定されていることに気づく人がいると思います。
実は、PPL の Constraint には、引数なしのコンストラクタが定義されておりません。
std::vector では 上記2つの関数で、引数無しのコンストラクタが必要とされます。
なので、ignoreを書かないとコンパイルエラーになってしまいます。

ここでは、変換対象から外すという強引な方法で、この問題を解決しています。
もっと、スリムな方法があるといいんですけど・・・



3.3. std::vectorを返す関数

ここでは、PPL::Constraint_SystemからPPL::Constraintの配列を返す関数を定義します。
/* ppl.extend.define.hpp */

std::vector<Constraint>
to_array(const Constraint_System& cs) {
  std::vector<Constraint> sv(cs.begin(), cs.end());
  return sv;
}

/* ppl.i */

%extend Constraint_System {
  std::vector<Constraint>
    to_a()
    { return to_array(*$self); }
};

これで、PPL::Constraint_System#to_a で配列が取得出来るようになります。
x = PPL::Variable.new(1)
y = PPL::Variable.new(2)

cs = PPL::Constraint_System.new
cs.insert(x < y)
cs.insert(x <= y)

p cs.to_a #=> [ -B + C > 0 , -B + C >= 0 ]
p cs.to_a.class #=> Array



3.4. 注意点

実は、SWIGで生成されるArrayには問題があります。
それは「変更不可能(freeze)な配列」が生成されるという問題です。
# 上記サンプルの続き
p cs.to_a.frozen? #=> true

よく考えれば、std::vectorとArrayは、受け取れるクラスに大きな違いがあります。
(静的と動的の宿命でもありますが)
そのため、生成される Array は freeze なのでしょう・・・

freezeであるため、破壊的メソッドは呼べません。
呼ぶ場合は、Object#dupする必要があります。 (Object#clone だと freeze は解除されません)



ここまでで、やりたいことのほとんどは出来ると思います。
自分の場合は、これでやりたいことの全てが終わりました。

ただ、継承解決で挙動おかしい部分があるので、そこは調査が必要だと思います。
( バグなら、治ってほしいなー )

公式リファレンスはまだまだ発展途中なので、実際に書いて動かすのが良いと思います。
それでは、良い SWIG LIFE を!

スポンサーサイト


Comments

Leave a Comment



10 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 - - - -

09

11


 
プロフィール

ひでたそ

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

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

Archive   RSS   Login

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