SWIG
以下、自分用メモ
Unit Testing C and C++ ... with Ruby and RSpec! を見つつ。スデに chroot な環境に swig も RSpec も導入済み。なので、試してみるか。まず資料に沿って c のソース用意。
cexample.h
/* cexample.h */ #ifndef CEXAMPLE_H #define CEXAMPLE_H #ifdef __cplusplus extern "C" { #endif char* returnString(char* input); double returnDouble(int input); void doNothing(); #ifdef __cplusplus } #endif #endif
cexample.c
/* cexample.h */ char* returnString(char* input) { return input; } double returnDouble(int input) { return (double) input; } void doNothing() {}
example.i
%module example %{ #include "cexample.h" %} %include "cexample.h"
で、swig 実行らしい
$ swig -ruby -Wall -o example_wrap.c example.i
あと、RSpec なソレ (cexample_spec.rb) を書いて
require File.dirname(__FILE__) + '/spec_helper' require 'example' describe "Example (C functions)" do it "should be a constant on Module" do Module.constants.should include('Example') end it "should have the methods defined in the C header file" do Example.methods.should include('returnString') Example.methods.should include('returnDouble') Example.methods.should include('doNothing') end end describe Example, ".returnString" do it "should return the input char * string as a Ruby string unchanged" do Example.returnString("bar!").should == "bar!" end end describe Example, ".returnDouble" do it "should return the input integer as a double" do Example.returnDouble(10).should == 10.0 end end describe Example, ".doNothing" do it "should exist, but do nothing" do lambda { Example.doNothing }.should_not raise_error end end
で、RSpec 実行。
$ spec cexample_spec.rb /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require': no such file to load -- ./spec_helper (LoadError) from /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:27:in `require' from ./cexample_spec.rb:1 from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/lib/spec/runner/example_group_runner.rb:14:in `load' from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/lib/spec/runner/example_group_runner.rb:14:in `load_files' from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/lib/spec/runner/example_group_runner.rb:13:in `each' from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/lib/spec/runner/example_group_runner.rb:13:in `load_files' from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/lib/spec/runner/options.rb:85:in `run_examples' from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/lib/spec/runner/command_line.rb:19:in `run' from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/bin/spec:4 from /usr/bin/spec:19:in `load' from /usr/bin/spec:19
む、オチた。spec_helper は何処に。ええと load-path を確認した方がよさげ。load-path は $: で確認できるらしい。(以下のソレは整形しております
$ ruby -e 'p $:;' ["/usr/local/lib/site_ruby/1.8", "/usr/local/lib/site_ruby/1.8/i486-linux", "/usr/local/lib/site_ruby/1.8/i386-linux", "/usr/local/lib/site_ruby", "/usr/lib/ruby/1.8", "/usr/lib/ruby/1.8/i486-linux", "/usr/lib/ruby/1.8/i386-linux", "."] $
ええと spec_helper で find したら以下
# find / -name 'spec_helper*' /usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/spec/spec_helper.rb /usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/examples/pure/spec_helper.rb /usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/failing_examples/spec_helper.rb /usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/pre_commit/spec/spec_helper.rb #
うーん。/usr/local/lib/site_ruby/1.8 あたりにリンク貼ってみるか。cexample_spec.rb のてっぺんはこうなってるんですが
require File.dirname(__FILE__) + '/spec_helper'
これはカレントディレクトリに置け、とゆー事かなぁ。
$ ruby -e 'p File.dirname(__FILE__)' "." $
コピーしてリトライ。
$ cp /usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/spec/spec_helper.rb . $ spec cexample_spec.rb /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require': no such file to load -- /home/rms/1.programming/1.sicp/spec/spec/spec_classes (LoadError) from /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:27:in `require' from ./spec_helper.rb:12 from /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require' from /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:27:in `require' from ./cexample_spec.rb:1 from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/lib/spec/runner/example_group_runner.rb:14:in `load' from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/lib/spec/runner/example_group_runner.rb:14:in `load_files' from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/lib/spec/runner/example_group_runner.rb:13:in `each' from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/lib/spec/runner/example_group_runner.rb:13:in `load_files' from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/lib/spec/runner/options.rb:85:in `run_examples' from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/lib/spec/runner/command_line.rb:19:in `run' from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/bin/spec:4 from /usr/bin/spec:19:in `load' from /usr/bin/spec:19 $
今度は spec_classes か。やっぱ load-path にも無理がありそう。find してみると
# find / -name 'spec_classes*' /usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/spec/spec/spec_classes.rb #
にあるんですが /usr/lib/ruby/1.8 にリンク作ってしまえ
# ln /usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/spec/spec/spec_classes.rb /usr/lib/ruby/1.8/spec_classes.rb # ln /usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/spec/spec/runner_spec.rb /usr/lib/ruby/1.8/runner_spec.rb # ln /usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/spec/spec/translator_spec.rb /usr/lib/ruby/1.8/tancelator_spec.rb #
駄目だ。load-path いぢった方が早そげ。てーか何故にカレントディレクトリなんだ、と。cexample_spec.rb の先頭は以下に修正。
# require File.dirname(__FILE__) + '/spec_helper' require 'spec_helper' require 'example'
あとコピッてきたファイル達も削除して cexample_spec.rb の先頭に以下を挿入してみる
dir = File.dirname("/usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/spec/spec") lib_path = File.expand_path("#{dir}") $LOAD_PATH.unshift lib_path unless $LOAD_PATH.include?(lib_path)
で、リトライ
$ spec cexample_spec.rb /usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/spec/../lib/spec/expectations/differs/default.rb:5: You must gem install diff-lcs to use diffing (RuntimeError) from /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require' from /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:27:in `require' from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/spec/spec_helper.rb:13 from /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require' from /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:27:in `require' from ./cexample_spec.rb:6 from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/lib/spec/runner/example_group_runner.rb:14:in `load' from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/lib/spec/runner/example_group_runner.rb:14:in `load_files' from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/lib/spec/runner/example_group_runner.rb:13:in `each' from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/lib/spec/runner/example_group_runner.rb:13:in `load_files' from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/lib/spec/runner/options.rb:85:in `run_examples' from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/lib/spec/runner/command_line.rb:19:in `run' from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/bin/spec:4 from /usr/bin/spec:19:in `load' from /usr/bin/spec:19
ヤり方的に微妙ですが、次の段階にイケたみたい。diff-lcs というソレを gem で入れれば良いのでしょうか。しかし gem 重い。で、リトライしてみましたが NG
$ spec cexample_spec.rb /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require': no such file to load -- example (LoadError) from /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:27:in `require' from ./cexample_spec.rb:7 from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/lib/spec/runner/example_group_runner.rb:14:in `load' from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/lib/spec/runner/example_group_runner.rb:14:in `load_files' from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/lib/spec/runner/example_group_runner.rb:13:in `each' from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/lib/spec/runner/example_group_runner.rb:13:in `load_files' from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/lib/spec/runner/options.rb:85:in `run_examples' from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/lib/spec/runner/command_line.rb:19:in `run' from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.3/bin/spec:4 from /usr/bin/spec:19:in `load' from /usr/bin/spec:19
こりゃアレだな。参照元が微妙なの??
先に RSpec の勉強した方が良さげだな。ruby 復習してみる必要もありそげ。しかし脱線してるのにもホドがある感満点。
続
てーか、よく考えたら C のコードをコンパイルとかしてないし。swig って何か、という部分からおさらいした方が良さげ。で、google 先生に聞いてみたらswigの使い方のメモ書きというコンテンツを発見。感謝しつつ。
まず extconf.rg という名前で以下
require "mkmf" $CFLAGS += " -Wall " $LOCAL_LIBS += " -llocallib " create_makefile("sample")
で、以下を実行、とある。
$ ruby extconf.rb; make; make install
とりあえず出力される makefile の中を見とく必要あり。で実行したら mkmf が load できねぇ、と叱られる。むむ、とウナりつつ現実トウヒ的昼寝。
起きてからいくつか google 先生にご教示頂く
なるほど、ruby1.8-dev か。Makefile もデキている模様。とりあえず make してみる
$ make gcc -I. -I/usr/lib/ruby/1.8/i486-linux -I/usr/lib/ruby/1.8/i486-linux -I. -fPIC -Wall -g -fno-strict-aliasing -O2 -fPIC -Wall -c cexample.c <built-in>:0: internal compiler error: Segmentation fault Please submit a full bug report, with preprocessed source if appropriate. See <URL:http://gcc.gnu.org/bugs.html> for instructions. For Debian GNU/Linux specific bug reporting instructions, see <URL:file:///usr/share/doc/gcc-4.1/README.Bugs>. make: *** [cexample.o] Error 1 $
げ。なんだそれは
$ gcc -v Using built-in specs. Target: i486-linux-gnu Configured with: ../src/configure -v --enable-languages=c,c++,fortran,objc,obj-c++,treelang --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --program-suffix=-4.1 --enable-__cxa_atexit --enable-clocale=gnu --enable-libstdcxx-debug --enable-mpfr --with-tune=i686 --enable-checking=release i486-linux-gnu Thread model: posix gcc version 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
gcc-3.4 にしてみるか。