gauche拡張モジュールの書き方(C++ライブラリ編)[途中:明日更新する]
c++のライブラリの場合は、以前紹介したものCライブラリの拡張モジュールの書き方と少し違います。opencvの一部の関数のbindingを書く例を参考に、C++ライブラリに対するgaucheの拡張モジュールの書き方を説明してみます。
gauche-cv-subset
今回作るパッケージの名前はgauche-cv-subsetという名前にします。また、graphics.cvというモジュール名でuseするとgauche-cv-subsetで提供された手続きが使えるようにします。
準備
gauche-packageを使って作業ディレクトリを作って作業していきます。
$ gauche-package generate gauche-cv-subset graphics.cv
gauche-packageはライブラリがCであることを前提として働くので、.soの作成にはデフォルトでgccを利用します。
c++のライブラリをコンパイルする際には、g++を利用するよう以下の2つのファイルを書き換えます。
- configure.ac
- Makefile.in
これらは"./DIST gen"を実行する前に行ってください。
configure.acの変更
AC_PROG_CXXという行を追加してください。以下は変更の前後のdiffです。(ちなみに、dnlで始まる行は単なるコメントです)
diff --git a/configure.ac b/configure.ac index ada52aa..f8d0d52 100644 --- a/configure.ac +++ b/configure.ac @@ -33,6 +33,10 @@ AC_PATH_PROG([GAUCHE_PACKAGE], gauche-package) AC_PATH_PROG([GAUCHE_INSTALL], gauche-install) AC_PATH_PROG([GAUCHE_CESCONV], gauche-cesconv) +dnl gauche-package doesn't know that the target library is written by C++. +dnl so We need to use AC_PROG_CXX macro for getting the name of C++ compiler. +AC_PROG_CXX + dnl Usually these parameters are set by AC_PROG_CC, but we'd rather use dnl the same one as Gauche has been compiled with. SOEXT=`$GAUCHE_CONFIG --so-suffix`
Makefile.inの変更
Makefile.inの変更は2点あります。CXXにC++のコンパイラの名前を格納する箇所と、依存するライブラリの場所を指定する箇所です。
以下が変更後のdiffです。
diff --git a/Makefile.in b/Makefile.in index c7081a4..cd4923e 100644 --- a/Makefile.in +++ b/Makefile.in @@ -16,6 +16,7 @@ VPATH = $(srcdir) # These may be overridden by make invocators DESTDIR = GOSH = @GOSH@ +CXX = @CXX@ GAUCHE_CONFIG = @GAUCHE_CONFIG@ GAUCHE_PACKAGE = @GAUCHE_PACKAGE@ INSTALL = @GAUCHE_INSTALL@ -C @@ -47,7 +48,8 @@ gauche_cv_subset_SRCS = $(srcdir)/gauche_cv_subset.c $(srcdir) all : $(TARGET) gauche_cv_subset.$(SOEXT): $(gauche_cv_subset_SRCS) - $(GAUCHE_PACKAGE) compile \ + $(GAUCHE_PACKAGE) compile --cc=$(CXX)\ + --libs="`pkg-config --libs opencv`" --cflags="`pkg-config --cflags opencv --local=$(LOCAL_PATHS) --verbose gauche_cv_subset $(gauche_cv_subset_S check : all
Makefile.inはconfigureで生成されるMakefileの雛型となるファイルです。今回は、"CXX = @CXX@"という記述を加えました。これは上記のconfigure.acに記述したAC_PROG_CXXによってc++のライブラリ名に書き換えられます。結果は、./configureで生成されるMakefileで確認してみてください。また、gauche-packageに渡すオプションも追加しています。
大雑把に言えば、以下のような順でファイルが生成されます。
- ./DIST gen
- autoconfが呼ばれる。(configure.acを利用)
- configureが生成される
- ./configure
Makefile.inとconfigure.acを書き換えたら、以前と同様にMakefileを生成しコンパイルしてみてください。
./DIST gen && ./configure && make && gosh -I. test.scm # ... # checking for g++... g++ # g++の存在をcheckしてます # checking whether the C++ compiler works... yes # ... # #--libs,--cc,--cflagsのオプションが渡されてます。g++が使われてます。 # /usr/bin/gauche-package compile --cc=g++\ # --libs="`pkg-config --libs opencv`" --cflags="`pkg-config --cflags opencv`" \ # --local= --verbose gauche_cv_subset ./gauche_cv_subset.c ./gauche_cv_subsetlib.stub # g++ -c -I/usr/lib/gauche/0.9/include -I/usr/include/opencv -fPIC -o 'gauche_cv_subset.o' './gauche_cv_subset.c' # ...
おそらく以下のようなエラーがでます。
Testing graphics.cv ... gosh: "error": Compile Error: dynamic linking of ./gauche_cv_subset.so failed: couldn't find initialization function _Scm_Init_gauche_cv_subset "./test.scm":8:(use graphics.cv)
Scm_Init_gauche_cv_subsetが見つからないと言われています。.hに追加して見えるようにしましょう。他にも色々と忘れていたことがありました。
- Scm_Init_gauche_cv_subsetのプロトタイプ宣言を追加(.h)
- 拡張子を.cから.cppにする
- 依存するライブラリをincludeする(.stub)
忘れてた作業を行いましょう。.cのファイルを.cppに変えて、ファイルに変更を加えます。
$ for i in *.c; do mv $i $(i%.c).cpp; done $ vi gauche_cv_subsetlib.stub # includeを追加 $ vi gauche_cv_subset.h # プロトタイプ宣言を追加 $ vi Makefile.in # .cを.cppに直す
変更後のdiffは以下です。
diff --git a/gauche_cv_subset.h b/gauche_cv_subset.h index cf51e82..0afb4df 100644 --- a/gauche_cv_subset.h +++ b/gauche_cv_subset.h @@ -18,6 +18,8 @@ SCM_DECL_BEGIN extern ScmObj test_gauche_cv_subset(void); +extern void Scm_Init_gauche_cv_subset(void); + /* Epilogue */ SCM_DECL_END diff --git a/gauche_cv_subsetlib.stub b/gauche_cv_subsetlib.stub index 22d28ef..cc9b7a2 100644 --- a/gauche_cv_subsetlib.stub +++ b/gauche_cv_subsetlib.stub @@ -3,6 +3,8 @@ ;;; " +#include <cvaux.h> +#include <highgui.h> #include \"gauche_cv_subset.h\" "
今度はテストが通ります。
$ make clean && make && gosh -I. test.scm # Testing graphics.cv ... # testing bindings in #<module graphics.cv> ... ok # test test-gauche_cv_subset, expects "gauche_cv_subset is working" ==> ok # passed.