C Structを初期化して別のRubyオブジェクトのパラメータとしてRubyクラスとしてラップするには?私は記憶を書き直していますが、それを修正する方法はわかりません。RubyにC構造体をラップする
require_relative 'my_extension'
class Address
def inspect
"Replaced #inspect: <Address: town:#{town}>"
end
end
class Person
def initialize
puts "init"
end
def print()
puts "Addr class #{@addr.inspect}"
end
end
foo1=Person.new
foo1.add_address("London")
foo1.print
foo2=Person.new
foo2.add_address("Paris")
foo1.print
foo2.print
foo1.print
Cコード、ルビーを拡張:
#include <stdio.h>
#include "ruby.h"
struct Address {
char * town;
};
static VALUE get_addr(VALUE self) {
return rb_iv_get(self,"@addr");
}
static VALUE wrap_address_get_town(VALUE self) {
struct Address * address;
Data_Get_Struct(self, struct Address, address);
return rb_str_new2(address->town);
}
VALUE foo_class;
VALUE address_wrapper_class;
void free_m(){
printf("free\n");//just for test
}
void add_address_t(VALUE self,VALUE new_town){
printf("add_address\n");
/*init new struct and add value to it*/
struct Address addr;
addr.town=StringValuePtr(new_town);
/*wrap struct*/
VALUE wrapped_address=Data_Wrap_Struct(address_wrapper_class, 0, free_m,&addr);
/*set it as instance variable*/
rb_iv_set(self,"@addr",wrapped_address);
}
static VALUE foo_class_alloc(VALUE self){
return self;
}
void Init_my_extension(){
foo_class = rb_define_class("Person", rb_cObject);
address_wrapper_class = rb_define_class("Address", rb_cObject);
rb_define_method(address_wrapper_class, "town", wrap_address_get_town, 0);
rb_define_method(foo_class, "add_address", add_address_t, 1);
}
出力が予期しない生産
Rubyのコード、私は別のクラスである、それらにアドレス変数をPersonクラスのインスタンスを作成し、追加したいです結果:
init
Addr class Replaced #inspect: <Address: town:London>
init
Addr class Replaced #inspect: <Address: town:Paris> //London expected
Addr class Replaced #inspect: <Address: town:�)> //another problem
Addr class Replaced #inspect: <Address: town:�)>
run
run
free
free
でFFIのドキュメントをチェックしてください。それは問題でした。ありがとう。構造体がローカルに定義されていれば、そのメモリが自動的に解放されることはわかりませんでした。それとも、私はそれを割り当てなければならないと思います。 mallocとALLOCの使用に違いはありますか? staticとして定義され、VALUEを返すのは良い習慣であるか、そうでなければなりませんか?それはそれなしで働いています... – matejuh
ALLOCは十分な空きメモリがあるかどうかチェックし、空きメモリがない場合は例外を発生させます。また、十分なメモリがない場合、GCを実行します。したがって、ALLOCを使用しない場合は、自分で行う必要があります。 関数が静的として定義されていない場合は、名前の衝突が発生する可能性があります。 –