概要
NativeExtensions でクラスやモジュールを複数定義した場合があると思います
構造体も異なる場合は別の .c
ファイルを作成したほうが良い場合があると思います
今回はその方法を紹介します
環境
- macOS 10.14.3
- Ruby 2.5.1p57
.c ファイルを追加する
まずは別のクラスを管理する C のコードを追加しましょう
touch ext/firstext/secondext.c
vim ext/firstext/secondext.c
#include <ruby.h>
void Init_secondext(void) {
VALUE se = rb_define_class("SecondExt", rb_cObject);
}
とりあえずクラスだけ定義しています
中身は空です
エントリーポイントとなる .c ファイルから参照する
NativeExtensions は Makefile 内で TARGET_ENTRY
を指定しているのですが 1 つしか指定しません
なので、そのエントリーポイントから追加した secondext.c
を参照します
vim ext/firstext/firstext.c
#... ↑ 省略
void Init_firstext(void) {
VALUE fe = rb_define_class("FirstExt", rb_cObject);
rb_define_alloc_func(fe, my_struct_alloc);
rb_define_method(fe, "set", wrap_set, 0);
rb_define_method(fe, "show", wrap_show, 0);
Init_secondext();
}
最後の Init_secondext();
を 1 行追加しただけです
今回はヘッダファイル (.h
) は作成しておらずソースファイル (.c
) だけです
同一階層にソースファイルを追加した場合は include しなくても別ソースファイルの関数を参照できました
コンパイル&テスト
bundle exec rake clean
bundle exec rake compile
でいつも通り lib/firstext.bundle
が作成されます
ちゃんと SecondExt
が使えるかテストしましょう
RSpec.describe FirstExt do
it "has a version number" do
expect(FirstExt::VERSION).not_to be nil
end
it "create a instance" do
cli = FirstExt.new
cli.set
cli.show
cli = SecondExt.new
end
end
bundle exec rake spec
でちゃんと SecondExt
クラスが new できるようになっていると思います
クラスが見つからないというエラーが出る場合は再度コンパイルし直してみてください
最後に
NativeExtensions の開発時に複数のソースファイルに分けて開発する際のポイントを紹介しました
基本的にはクラスやモジュール単位でソースファイルも分かると良いかなと思います
今回はヘッダファイルを作成していません
お作法的にはちゃんとヘッダファイルを書くべきです
他に気になるワードとしては depend という機能がありこれに依存関係を書いておくと依存関係のあるファイルを自動でコンパイルしてくれます
rake-compiler
を使っている場合はもしかしたら不要っぽかったので今回は使っていません
0 件のコメント:
コメントを投稿