ラベル swig の投稿を表示しています。 すべての投稿を表示
ラベル swig の投稿を表示しています。 すべての投稿を表示

2009年6月8日月曜日

cmake で swig と php5 (2)

こちらの続きです。Ubuntu のタグがはってありますが、特に Ubuntu に特化した内容ではありません。
参考URLから、FindPHP5.cmake を生成します。テキストを切り出して php5.diff にしたと仮定
$ patch -p1 < php5.diff

こいつを、CMake の /share/CMake/Modules/ 下にコピーします。cmake のバージョンが上がると、標準のモジュールとして取り込まれているかもしれません。
CMakeLists.txt 中での使い方は
FIND_PACKAGE (PHP5)
######################################################
# Manual set for PHP5
######################################################
#SET (PHP5_INCLUDE_PATH "/usr/include/php5")
#SET (PHP5_EXECUTABLE "/usr/bin/php5")
IF (NOT PHP5FOUND)
MESSAGE ("---------------------------------------")
MESSAGE ("          !!! FATAL ERROR !!!          ")
MESSAGE ("---------------------------------------")
MESSAGE (FATAL_ERROR "PHP5 does not found.")
ENDIF (NOT PHP5FOUND)



FIND_PACKAGE (SWIG REQUIRED)

INCLUDE (${SWIG_USE_FILE})



SET (CMAKE_SWIG_FLAGS "")

SET_SOURCE_FILES_PROPERTIES (hoge.i PROPERTIES CPLUSPLUS ON)

SWIG_ADD_MODULE(hoge php5 hoge.i hoge.cpp fuga.cpp)



INCLUDE_DIRECTORIES (${PHP5_INCLUDE_DIR} ${PHP5_MAIN_INCLUDE_DIR}
${PHP5_TSRM_INCLUDE_DIR} ${PHP5_ZEND_INCLUDE_DIR} ${PHP5_REGEX_INCLUDE_DIR}
${PHP5_EXT_INCLUDE_DIR} ${PHP5_DATE_INCLUDE_DIR} ${PHP5_STANDARD_INCLUDE_DIR}
${INCLUDE_DIRECTORIES})





などとして、
$ cmake . -DCMAKE_BUILD_TYPE=Release

ビルドをすると、"hoge.php" と "hoge.so" が生成されます。
あとは、runme.php を
<?php
require "hoge.php";

$hoge = new fuga();
$hoge->bar();
?>

という感じで使えます。

ここからは、Ubuntu 固有かもしれません。
/etc/php5/conf.d/hoge.ini を
# configuration for hoge module
extension=hoge.so

としてやり、
/usr/lib/php5/20060613
の下に、hoge.so をコピーしました。なんかしらんけど、こんなんでコマンド・プロンプトからは動きました。

追記:CentOS 5.2 では、swig のバージョンが古くてコンパイルできません。rpmforge の swig は、輪をかけて古いです。という事で、本家からソースをダウンロードして
$ ./configure --prefix=/usr
$ make install

しました。
追記:CentOS 5.2 では、hoge.so を /usr/lib64/php/modules 下にコピーすればOKでした。i386 環境では、/usr/lib/php/modules だと推測されます。

2009年6月5日金曜日

cmake で swig と php5

 さっそく、ubuntu 環境で巡回セールスマン問題を解くクラスを perl 版、php5 版で作成してみました。比較的あっさりと動きました。後で、cmake で swig & php5 な構築をするための手順を書こうと思います。

参考は、これ

2009年3月1日日曜日

swig boost_random 今度はrubyで

 そもそも自分が使わないものを作ってどうすんだ?って部分はありますが、いつかは swig ってみたいと思っていたのも事実です。で、需要の方がサッパリわかりませんが、swig でベースを書いても案外自分の使いたい言語に落とし込む cmake 等の作業の方で、敷居が高いのかもしれない?と思って、今回は ruby してみました。

 CMakeLists.txt の後半 Perl 部分を以下のように書き換えます

FIND_PACKAGE (Ruby)

FIND_PACKAGE (SWIG REQUIRED)
INCLUDE (${SWIG_USE_FILE})

SET (CMAKE_SWIG_FLAGS "")
SET_SOURCE_FILES_PROPERTIES (random.i PROPERTIES CPLUSPLUS ON)
SWIG_ADD_MODULE(boost_random ruby random.i random.cpp)

INCLUDE_DIRECTORIES (${RUBY_INCLUDE_PATH} ${INCLUDE_DIRECTORIES})

IF (WIN32)
IF (NOT RUBY_LIBRARY)
SET (RUBY_LIBRARY "c:/program files/ruby-1.8/lib/msvcrt-ruby18.lib")
ENDIF (NOT RUBY_LIBRARY)
ENDIF (WIN32)
IF (RUBY_LIBRARY)
SWIG_LINK_LIBRARIES(boost_random "${RUBY_LIBRARY}")
ENDIF (RUBY_LIBRARY)


続いて runme.rb です。

require 'boost_random'

print "Uniform_mt19937\n";
mt19937 = Boost_random::Uniform_mt19937.new( 32 );
100.times do
print mt19937.get().to_s + ",";
end;

print "\Exp_necuyer1988\n";
ecuyer = Boost_random::Exp_ecuyer1988.new( 3, 4, 2.0 );
100.times do
print ecuyer.get().to_s + ",";
end;

print "\nNormal_lagged_fibonacci2281\n";
fibo = Boost_random::Norm_lagged_fibonacci2281.new( 50.0, 10.0 );
100.times do
print fibo.get().to_s + ",";
end;

print "\nLognormal kreutzer1986\n";
kreu = Boost_random::Log_kreutzer1986.new( 5, 0.5, 2.0 );
100.times do
print kreu.get().to_s + ",";
end;

 クラス命名規則が煩いな…と思いました。swig だと、いろんな言語を対象にする訳ですが、中には大文字小文字を区別しない言語やアンダーバーを使えない言語もあるかもしれません。

 尚、テストは windows 上の ActiveScriptRuby で行いました。msvc6.0 が必要です。どうしても…という場合は、config.h

#if _MSC_VER != 1200
//#error MSC version unmatch: _MSC_VER: 1200 is expected.
#endif

をすれば動作しますが、ランタイムのアロケータが異なっているために、メモリリークを引き起こしかねないので、やめましょう(ruby の内部構造を知らないので、可能性の話です)。

2009年2月28日土曜日

swig boost_random クリア!

 全部、クリアしました。という訳で、再度、告知します。


 gcc の typeinfo が返すアホな名前ですが、最終的には、std::map<std::string,std::string> によりマッピングを作成しておいて正しい名前に変換するという手法でクリアしました。これなら、どのコンパイラもクリアだと思いたい。

 cmake の TRY_RUN の挙動ですが、コンパイラ・オプションは別途指定しなければならないようです。"-I /usr/local/include/boost_1_38" というような追加情報は、COMPILE_DEFINITIONS に指定しなければなりませんでした。windows 上では環境変数 include に boost も指定していたので windows 上のみ作動していたという訳でした。

追伸:
 ツンデレのお題、俺、体育会系だし、わかんねーよ(Don't think, type. by BRUCE LEE 2nd)。
と思っていたのですが、typeid の返す名前をツンして、
  • gcc : typename コンバータ使ってね
  • msvc : 完璧ね
とデレするパターンを朝に閃きました。でも、こっちに夢中で時間切れとなりますた。

2009年2月27日金曜日

swig boost_random どないせーちゅーねん

 ニュートン法というのをご存知だろうか?解を求めるのに反復しながら近づくというものだ。このニュートン法のように、今日は windows (msvc) と ubuntu (gcc) を何度も往来した。

 まず、cmake の挙動が違う。TRY_RUN が windows 上では、うまく動作するのに、ubuntu 上ではエラーを吐いて止まる。

 次に、gcc_primitive_type_name_hack 中の int の扱いではまる。まさにニュートン法で発散する状況だ。msvc では、long 扱いでないと、boost::random のコンストラクタが動作しないものが出てくる。gcc では、その逆で int 扱いでないと、boost::random のコンストラクタが動作しないものが出てくる。困った事に sizeof(int) == sizeof(long) だ。だ。だ。だ。だ。だだだだだだだだだだだだだ。

 お願いだ、primitive type に関しては、typeinfo は、ちゃんとした名前を返してくれ~

2009年2月26日木曜日

swig boost_random gcc の typeinfo

 えー、ubuntu 上でも動作するようになりました。プリプロセッサだけでなく、gcc の typeid にもやられてました。しょうがないので、こんな関数を作って、お茶を濁すことに…。

const char* gcc_primitive_type_name_hack( size_t primitive_size, bool is_signed, bool is_modulo ) {
// std::cout << typeid( int ).name();
// i
// ... to be haniwa. (O o O)
if( !is_modulo ) {
if( primitive_size == sizeof(double) ) return "double";
else if( primitive_size == sizeof(float) ) return "float";
else if( primitive_size == sizeof(long double) ) return "long double";
} else {
if( is_signed ) {
if( primitive_size == sizeof(char) ) return "char";
else if( primitive_size == sizeof(int) ) return "int";
else if( primitive_size == sizeof(short) ) return "short";
else if( primitive_size == sizeof(long) ) return "long";
else if( primitive_size == sizeof(long long) ) return "long long";
} else {
if( primitive_size == sizeof(char) ) return "unsigned char";
else if( primitive_size == sizeof(int) ) return "unsigned int";
else if( primitive_size == sizeof(short) ) return "unsigned short";
else if( primitive_size == sizeof(long) ) return "unsigned long";
else if( primitive_size == sizeof(long long) ) return "unsigned long long";
}
}
return "unknown";
}

swig boost_random 移植性は難しい

 今度こそ、コンパイルも通るだろ…と思ったら、家の ubuntu 環境では、またもエラーになってしまった。その原因は、型のズレによるもの。よくよく考えたら、random_class_generator.cpp を作成したのは、プラットフォーム間の違いにより生じるソースの違いを動的に吸収しようと思っての事だったので、ubuntu 上でも random_class_generator.cpp からコンパイルして実行する事にした。

 コンパイルしてみると、preprocessor の部分で引っかかった。

BOOST_PP_CAT( "hoge_", BOOST_PP_STRINGIZE(x) ) であるが、x に fuga が渡された時、MSVC では、"hoge_fuga" に展開されるが、gcc では ""hoge_""fuga"" に展開されてしまいエラーになった。MSVC に逆戻りして、チェックしてみないと、なんとも言えないが、正しくは
BOOST_PP_STRINGIZE( BOOST_PP_CAT(hoge_, x) ) とすべきなのだろうか? 'hoge_' は文字通り展開され、'x' は 'fuga' に展開されて ## により結合されるので、心情的に、かなり気持ち悪い。

 今回の教訓。プリプロセッサ、面白かったけど、罠がいっぱい。できるならば使わない方が良い。

 他にも、いろいろと引っかかっている。一筋縄ではいかないもんだ・・・。これは、まだまだ完成しそうにない。

2009年2月25日水曜日

swig boost_random 意味がわからん

 ubuntu 環境でコンパイルしてみたら identifier before ‘&’ token というようなエラーになって、全く意味がわからなかった。
 どうやら、クラスのメンバ関数名に random() という名前を使ったのがお気に召さなかったらしい。include ガードとかも念のために追加して、また、手を加えたらポストします。

swig 欲張りすぎたかも

 とりあえず、active_perl では動作した。しかし、ほとんどテストはしていない。cmake 用の CMakeFiles.txt も適当に書いたので、そのまんまではコンパイルもままならないかもしれない。ここまでやったが、私がこれを使う事は、まず無いだろう(少々のコンバータとかでも、C++で書いちゃいますから~)。そんなわけで、一応、貼っときます。煮るなり、焼くなり、好きにしてください。



  • direct_* は直接呼出し
  • uniform_* は、[0,1) の一様確率
  • exp_* は 指数分布
  • norm_* はガウス分布
  • log_* は対数ガウス分布
となってます。コンパイルには、boost が必要です。

後で、もうちょっと CMakefilesCMakeLists.txt をまじめに書く予定だけど、移り気なので約束が果たされるかどうか…

追記: よく考えたら、余計なメンバを定義していたので無駄にサイズが増えて勿体無いお化けに怒られそう…という事で、ポストしてから、AM3:09には、修正したのをアップし直しました。
更に追記:Ubuntuでコンパイルが通らない。なんで~?

2009年2月23日月曜日

swig 怪しい経過

 こちらですが、とりあえず、動作させる所までは来ました(手を入れないと動かないです)。しかし、わかった事が2点。これは、かなり怪しい領域に突入してきました。
  1. メンバ配置のバイト・アライメントを考慮に入れなければならない
  2. 仮想継承のサイズを考慮に入れなければならない
 以上をクリアすれば、今の方向性で問題なさそうです。バイト・アライメントなんて、コンパイルする環境によって変わるし、仮想継承のサイズなんて実装依存です。困ったもんだ…。

追記: バイト・アライメントをコード中で取得する方法って、何か無いだろうか? boost::pool でも参考にする?

2009年2月22日日曜日

swig 経過

 とりあえず、現在は、こんな感じ…。BOOST_PP_IF( BOOST_PP_EQUAL( ... などとやっていたが、さすがにこれは、やり過ぎでやめた。boost random の引数等が違っていて、さすがにこれは等価には扱いきれなかった。欲を言えば、seed_type とか seed_arg_count とかを定義していて欲しかったかも?

namespace {
char copyright[] =
"";
}

#include <iostream>
#include <typeinfo>
#include <fstream>
#include <boost/preprocessor.hpp>
#include <boost/random.hpp>

#define RANDOM_TYPE_COUNT 16
#define RANDOM_TYPE_ARRAY ( RANDOM_TYPE_COUNT, ( \
minstd_rand, \
rand48, \
ecuyer1988, \
kreutzer1986, \
hellekalek1995, \
mt11213b, \
mt19937, \
lagged_fibonacci607, \
lagged_fibonacci1279, \
lagged_fibonacci2281, \
lagged_fibonacci3217, \
lagged_fibonacci4423, \
lagged_fibonacci9689, \
lagged_fibonacci19937, \
lagged_fibonacci23209, \
lagged_fibonacci44497 \
) )

#define NTH_ecuyer1988 2
#define NTH_lagged_fibonacci607 7

#define INC_OP( r, i ) BOOST_PP_INC(i)
#define PRED( r, i ) BOOST_PP_LESS(i,RANDOM_TYPE_COUNT)

#define NEXT_LINE ofs << "\n";

#define ALGO_CLASS_NAME( x ) BOOST_PP_CAT( "algo_", BOOST_PP_STRINGIZE(x) )

// for random_def.hpp
void print_type( std::ostream& os, const char* class_name, size_t class_size ) {
os << "struct " << class_name << " {" << std::endl;
os << " char pos[" << class_size << "];" << std::endl;
os << "};" << std::endl;
}
#define PRINT_TYPE_X( x ) { \
print_type( ofs, BOOST_PP_STRINGIZE(x), sizeof(x) ); \
NEXT_LINE \
print_type( ofs, BOOST_PP_CAT("valiate_generator_", BOOST_PP_STRINGIZE(x)), sizeof(variate_generator<x,uniform_real<> >) ); \
NEXT_LINE \
}
#define PRINT_TYPE( r, i ) PRINT_TYPE_X( BOOST_PP_ARRAY_ELEM(i,RANDOM_TYPE_ARRAY) )

// for random_retype.hpp
void print_retype( std::ostream& os, const char* base_name ) {
os << "typedef variate_generator< " << base_name << ", uniform_real<> > ";
os << "variate_generator_" << base_name << ";" << std::endl;
}
#define PRINT_RETYPE_X( x ) { \
print_retype( ofs, BOOST_PP_STRINGIZE(x) ); \
NEXT_LINE \
}
#define PRINT_RETYPE( r, i ) PRINT_RETYPE_X( BOOST_PP_ARRAY_ELEM(i,RANDOM_TYPE_ARRAY) )


// for random.hpp
void print_class( std::ostream& os, const char* class_name, const char* result_name, int array_number ) {
os << "class algo_" << class_name << " {" << std::endl;
os << "private:" << std::endl;
os << " " << class_name << " generator_;" << std::endl;
os << " variate_generator_" << class_name << " variator_;" << std::endl;
os << "public:" << std::endl;
os << " algo_" << class_name << "( ";
if( array_number == NTH_ecuyer1988 ) {
os << result_name << " seed1, " << result_name << " seed2);" << std::endl;
} else if( array_number >= NTH_lagged_fibonacci607 ) {
os << ");" << std::endl;
} else {
os << result_name << " seed);" << std::endl;
}
os << " double random();" << std::endl;
os << " " << result_name << " numeric_random();" << std::endl;
os << "};" << std::endl;
}
#define PRINT_CLASS_X( x, i ) { \
print_class( ofs, BOOST_PP_STRINGIZE(x), typeid( x::result_type ).name(), i ); \
NEXT_LINE \
}
#define PRINT_CLASS( r, i ) PRINT_CLASS_X( BOOST_PP_ARRAY_ELEM(i,RANDOM_TYPE_ARRAY), i )

// for random.cpp
void print_implement( std::ostream& os, const char* class_name, const char* result_name, int array_number ) {
os << "///////////////////////////////////////" << std::endl;
os << "// " << class_name << std::endl;
os << "///////////////////////////////////////" << std::endl;
os << class_name << "::" << class_name << "(";
if( array_number == NTH_ecuyer1988 ) {
os << result_name << " seed1, " << result_name << " seed2) :" << std::endl;
os << " generator_(seed1,seed2)," << std::endl;
} else if( array_number >= NTH_lagged_fibonacci607 ) {
os << ") :" << std::endl;
os << " generator_()," << std::endl;
} else {
os << result_name << " seed) :" << std::endl;
os << " generator_(seed)," << std::endl;
}
os << " variator_(generator_,uniform_real<>())" << std::endl;
os << "{}" << std::endl;
os << std::endl;
os << "double " << class_name << "::random() { return variator_(); }" << std::endl;
os << result_name << " " << class_name << "::numeric_random() { return generator_(); }" << std::endl;
os << std::endl;
}
#define PRINT_IMPLEMENT_X( x, i ) { \
print_implement( ofs, ALGO_CLASS_NAME(x), typeid( x::result_type ).name(), i ); \
}
#define PRINT_IMPLEMENT( r, i ) PRINT_IMPLEMENT_X( BOOST_PP_ARRAY_ELEM(i,RANDOM_TYPE_ARRAY), i )

// for random.i
void print_ignore( std::ostream& os, const char* class_name ) {
os << "%ignore " << class_name << "::generator_;" << std::endl;
os << "%ignore " << class_name << "::variator_;" << std::endl;
}
#define PRINT_IGNORE_X( x ) print_ignore( ofs, ALGO_CLASS_NAME(x) );
#define PRINT_IGNORE( r, i ) PRINT_IGNORE_X( BOOST_PP_ARRAY_ELEM(i,RANDOM_TYPE_ARRAY) )

using namespace boost;

void print_random_def() {
std::ofstream ofs( "random_def.hpp" );

ofs << "// random_def.hpp\n";
NEXT_LINE
BOOST_PP_FOR( 0, PRED, INC_OP, PRINT_TYPE )
NEXT_LINE
print_type( ofs, "uniform_base", sizeof(uniform_real<>) );
}

void print_random_retype() {
std::ofstream ofs( "random_retype.hpp" );

ofs << "#include <boost/random.hpp>\n";
ofs << "using namespace boost;\n";
NEXT_LINE
BOOST_PP_FOR( 0, PRED, INC_OP, PRINT_RETYPE )
NEXT_LINE
ofs << "typedef uniform_real<> uniform_base;" << std::endl;

}

void print_random_hpp() {
std::ofstream ofs( "random.hpp" );

ofs << "#ifdef SWIG\n";
ofs << "#include \"random_def.hpp\"\n";
ofs << "#else\n";
ofs << "#include \"random_retype.hpp\"\n";
ofs << "#endif\n";
NEXT_LINE

BOOST_PP_FOR( 0, PRED, INC_OP, PRINT_CLASS )
}

void print_random_cpp() {
std::ofstream ofs( "random.cpp" );

ofs << "#include \"random.hpp\"\n";
NEXT_LINE
BOOST_PP_FOR( 0, PRED, INC_OP, PRINT_IMPLEMENT )
}

void print_random_i() {
std::ofstream ofs( "random.i" );

ofs << "/* File : random.i */\n";
NEXT_LINE
ofs << "%module boost_random\n";
NEXT_LINE
ofs << "%{\n";
ofs << "#include \"random.hpp\"\n";
ofs << "%}\n";
NEXT_LINE
BOOST_PP_FOR( 0, PRED, INC_OP, PRINT_IGNORE )
NEXT_LINE
ofs << "%ignore uniform_base;\n";
NEXT_LINE
ofs << "/* Let's just grab the original header file here */\n";
ofs << "%include \"random.hpp\"\n";
}

int main() {

print_random_def();
print_random_retype();
print_random_hpp();
print_random_cpp();
print_random_i();

return 0;
}

2009年2月21日土曜日

swig のはずが boost preprocessor

 swig で boost::random をラッピングしたクラスを作ってみようと、あれこれ構想しているうちに、何故か脱線してしまい。boost preprocessor に夢中になってしまった。そもそも、こういう方向性でいいのかどうか7割ぐらいの確信でもって、どんどん突っ走ってしまっていいのだろうか?という一抹の不安もぬぐえない…。が、能天気な性格なのでよしとする。

 プリプロセッサも面白いね。


#include <iostream>
#include <typeinfo>
#include <fstream>
#include <boost/preprocessor.hpp>
#include <boost/random.hpp>

#define RANDOM_TYPE_COUNT 16
#define RANDOM_TYPE_ARRAY ( RANDOM_TYPE_COUNT, ( \
minstd_rand, \
rand48, \
ecuyer1988, \
kreutzer1986, \
hellekalek1995, \
mt11213b, \
mt19937, \
lagged_fibonacci607, \
lagged_fibonacci1279, \
lagged_fibonacci2281, \
lagged_fibonacci3217, \
lagged_fibonacci4423, \
lagged_fibonacci9689, \
lagged_fibonacci19937, \
lagged_fibonacci23209, \
lagged_fibonacci44497 \
) )

#define INC_OP( r, i ) BOOST_PP_INC(i)
#define PRED( r, i ) BOOST_PP_LESS(i,RANDOM_TYPE_COUNT)


#define PRINT_TYPE( r, i ) { \
ofs << "struct " << BOOST_PP_STRINGIZE(BOOST_PP_ARRAY_ELEM(i,RANDOM_TYPE_ARRAY)) << " {\n"; \
ofs << " char pod[" << sizeof(BOOST_PP_ARRAY_ELEM(i,RANDOM_TYPE_ARRAY)) << "];\n"; \
ofs << "};\n" << std::endl; \
ofs << "struct valiate_generator_" << BOOST_PP_STRINGIZE(BOOST_PP_ARRAY_ELEM(i,RANDOM_TYPE_ARRAY)) << " {\n"; \
ofs << " char pod[" << sizeof(variate_generator<BOOST_PP_ARRAY_ELEM(i,RANDOM_TYPE_ARRAY),uniform_real<> >) << "];\n"; \
ofs << "};\n" << std::endl; \
}

#define PRINT_RETYPE( r, i ) { \
ofs << "typedef variate_generator< " << BOOST_PP_STRINGIZE(BOOST_PP_ARRAY_ELEM(i,RANDOM_TYPE_ARRAY)) << ", uniform_real<> >"; \
ofs << " variate_generator_" << BOOST_PP_STRINGIZE(BOOST_PP_ARRAY_ELEM(i,RANDOM_TYPE_ARRAY)) << ";\n"; \
}


#define PRINT_CLASS( r, i ) { \
ofs << "class algo_" << BOOST_PP_STRINGIZE(BOOST_PP_ARRAY_ELEM(i,RANDOM_TYPE_ARRAY)) << " {\n"; \
ofs << "private:\n"; \
ofs << " " << BOOST_PP_STRINGIZE(BOOST_PP_ARRAY_ELEM(i,RANDOM_TYPE_ARRAY)) << " generator_;\n"; \
ofs << " variate_generator_" << BOOST_PP_STRINGIZE(BOOST_PP_ARRAY_ELEM(i,RANDOM_TYPE_ARRAY)) << " variater_;\n"; \
ofs << "public:\n"; \
ofs << " algo_" << BOOST_PP_STRINGIZE(BOOST_PP_ARRAY_ELEM(i,RANDOM_TYPE_ARRAY)) << "( unsigned int32 seed ); \n"; \
ofs << " double random(); \n"; \
ofs << " " << typeid( BOOST_PP_ARRAY_ELEM(i,RANDOM_TYPE_ARRAY)::result_type ).name() << " numric_random();\n"; \
ofs << "};\n" << std::endl; \
}


using namespace boost;

void print_random_def() {
std::ofstream ofs( "random_def.hpp" );

ofs << "// random_def.hpp\n";

BOOST_PP_FOR( 0, PRED, INC_OP, PRINT_TYPE )

ofs << "struct uniform_base {\n";
ofs << " char pod[" << sizeof(uniform_real<>) << "];\n";
ofs << "};\n";

}

void print_random_retype() {
std::ofstream ofs( "random_retype.hpp" );

ofs << "#include <boost/random.hpp>\n";
ofs << "using namespace boost;\n";

BOOST_PP_FOR( 0, PRED, INC_OP, PRINT_RETYPE )

ofs << "typedef uniform_real<> uniform_base;" << std::endl;

}

void print_random_hpp() {
std::ofstream ofs( "random.hpp" );

ofs << "#ifdef SWIG\n";
ofs << "#include \"random_def.hpp\"\n";
ofs << "#else\n";
ofs << "#include \"random_retype.hpp\"\n";
ofs << "#endif\n";
ofs << "\n";

BOOST_PP_FOR( 0, PRED, INC_OP, PRINT_CLASS )
}

int main() {

print_random_def();

print_random_retype();

print_random_hpp();

return 0;
}

2009年2月14日土曜日

swig ってどうよ?

 ちょい突っ込んでみたが、何も全部をそのまま移植しようとしなくても良かろうに…と思うのである。%ignore により、こいつは無視してくだされ…という指定もできるのだが、ラッパーをかまそうと思ってもできない。これについては、後述する。

 だいたい、ruby のサンプルに template はあるのに、perl のサンプルに template はない。無理矢理移植をしてコンパイルしてみたが、なるほど、コンパイルが通らない。C2061 とか出てて、検索してみたら、2ch にも投稿があり、先駆者の屍が累々としていそうである。だいたい、現行 C++ の template をスクリプトにそのまま展開しようというのは狂気の沙汰であるようにも思える。

 %ignore で無視できるメンバを指定できるのに加えて、#include <hoge.hpp> の中身全てを無視するディレクティブ(指令)が欲しいところである。最終的には、sizeof(無視されたメンバ) さえ取得できれば辻褄が合うのではないかと思う(確信は無い)。

 で、ためしに boost::mt19937 のメンバを char dummy[4]; ぐらいで置き換えて、コンパイルしてみたら、実行時に見事にお亡くなりになる。


#include <boost/random.hpp>
#include <iostream>

int main() {
std::cout << sizeof(boost::mt19937) << std::endl;
return 0;
}


を実行してみると、4996 と表示された…。そんなにデカかったのかよorz...(そりゃそうか)。
気を取り直して、char dummy[4996]; で再度実行すると、うまく動いているような気がする(ただし、表示される数値は unsigned のレンジではなく signed のレンジで怪しさ倍増)。うーん…、swig ってどうよ?

2009年2月13日金曜日

swigってみた

 なんとなく swig
どの言語を対象にしても良いけれでも、一応メジャーな Perl にしてみた。今回は windows で、ちょい試してみたので、swig は swigwin-1.3.38 をチョイス。
 cygwin は、どうも好きになれないのと、ActivePerl で swig できるらしいので、ActivePerl 5.10 をダウンロードしてインストール。ここから、ややしばらく悩んだ…。
 swigwin-1.3.38\Examples\perl5\simple のIDEを開いて、コンパイルしてみると、PERL5_INCLUDE, PERL5_LIB の環境変数が設定されていないと怒られ、EXTERN.h とかが無いと言われる。そんなもん、どこにあんねん?とディレクトリを見たが、それらしい所が無い、検索しても、どこにあるといった情報が皆無。ディレクトリを検索してみて、ようやく見つけた。

PERL5_INCLUDE=C:\Perl\lib\CORE
PERL5_LIB=C:\Perl\lib\CORE\perl510.lib

を設定し、コンパイル。OK、うまくいった。

C:\downloads\swigwin-1.3.38\Examples\perl5\simple>perl runme.pl
The gcd of 42 and 105 is 21
Foo = 3
Foo = 3.1415926

ちゃんと動いているようだ。