C Structを初期化し、別のRubyオブジェクトのパラメーターとしてRubyクラスとしてラップする方法は?メモリを書き換えていますが、修正方法がわかりません。
Rubyコード、Personクラスのインスタンスを作成し、それらにAddress変数を追加します。これは別のクラスです。
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
Rubyを拡張する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);
}
出力は予期しない結果を生成します:
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