2

RubyでFoo::Barを記述していて、C拡張機能としてBarにメソッドを追加したい場合。今、CでFoo :: Barを次のように作成すると、次のようになります。

static VALUE Foo;
static VALUE Bar;

static VALUE 
print_string(VALUE self, VALUE string) {
  printf("%s", StringValuePtr(string));
  return Qnil;
}

void Init_foo() {
    Foo = rb_define_module("Foo");
    Bar = rb_define_class_under(Foo, "Bar", rb_cObject);
    rb_define_method(Bar, "print_string", print_string, 1);
}

しかし、問題は次のとおりです。

ruby-1.9.2-p180 :001 > require 'ext/foo'   #=> ["Foo"]
ruby-1.9.2-p180 :002 > f = Foo::Bar.new   #=> #<Foo::Bar:0x000001046bce48>
ruby-1.9.2-p180 :003 > f.original_ruby_method
NoMethodError: undefined method `original_ruby_method' for #<Foo::Bar:0x000001046bce48>

したがって、基本的に元のFoo::Barを上書きしています。上書きせずに拡張するにはどうすればよいですか?

4

3 に答える 3

3

私はこの問題を解決する方法を考え出しました。

void Init_foo() {
    rb_eval_string("require './lib/foo'");
    VALUE Bar = rb_path2class("Foo::Bar");
    rb_define_method(Bar, "print_string", print_string, 1);
}
于 2011-06-22T16:29:55.240 に答える
1

C拡張機能からRubyコードを要求するソリューションの代替手段は、Rubyコードから拡張機能を要求することです。

require 'foo.so'またはrequire 'ext/foo.so'(コンパイルされたライブラリが終了する場所に応じて)をに追加lib/foo.rbし、クライアントコードで通常どおりに呼び出します(ロードパス上にあるとrequire 'foo'想定)。lib

私はそれをこのように行うことはより明確でより一般的だと思います。

.soプラットフォームが何か他のものを生成している場合でも、サフィックスを使用できることに注意してください。つまり、実際のファイルが。である場合でも、Macで機能します.bundle

于 2011-06-22T18:05:00.997 に答える
1

少し隠された関数-それを見つけるためにソースを掘り下げる必要がありましたが、rb_const_get既存のモジュールとクラスへの参照を取得するために使用できます。

void Init_foo() {
  Foo = rb_const_get( rb_cObject, rb_intern("Foo");
  Bar = rb_const_get( Foo, rb_intern("Bar");
  rb_define_method(Bar, "print_string", print_string, 1);
}

クラス/モジュールが存在しない場合に作成されるようにする場合:

void Init_foo() {
  if ( rb_const_defined( rb_cObject, rb_intern("Foo") ) )
    Foo = rb_const_get( rb_cObject, rb_intern("Foo");
  else
    Foo = rb_define_module("Foo");

  if ( rb_const_defined( Foo, rb_intern("Bar") ) )
    Bar = rb_const_get( Foo, rb_intern("Bar");
  else
    Bar = rb_define_class_under(Foo, "Bar", rb_cObject);

  rb_define_method(Bar, "print_string", print_string, 1);
}
于 2012-03-08T14:11:31.840 に答える