From: Bryan Richardson Date: 2008-05-06T06:41:48+09:00 Subject: Re: Need more help with Ruby and C ------=_Part_21962_13270493.1210023708260 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Content-Disposition: inline Okay, new question... still in line with what I've been asking already. Say I have the following: typedef struct { char* name; } Foo; static VALUE rb_cBar; static VALUE rb_cTest; static VALUE foo_new(VALUE self) { Foo* f; VALUE info; info = Data_Make_Struct(rb_cTest, Foo, 0, free, f); rb_obj_call_init(info, 0, 0); return info; } static VALUE foo_init(VALUE self) { VALUE str; char* name = "Bryan"; str = rb_str_new2(name); rb_iv_set(self, "@name", str); return self; } static VALUE test(VALUE self, VALUE arg) { Foo* f; Data_Get_Struct(arg, Foo, f); printf("Name: %s\n", f->name); return Qnil; } void Init_power_flow() { rb_cBar = rb_define_class("Bar", rb_cObject); rb_cTest = rb_define_class("Test", rb_cObject); rb_define_method(rb_cBar, "test", test, 1); rb_define_method(rb_cBar, "new_foo", foo_new, 0); rb_defien_method(rb_cTest, "initialize", foo_init, 0); } If I do the following, everything works perfectly and I see my name printed on the screen: b = Bar.new f = b.new_foo b.test(f) // prints "Bryan" However, say I change the foo_new method to be the following: static VALUE foo_new(VALUE self) { Foo* f; VALUE info; f = ALLOC(Foo); f->name = "Bryan"; info = Data_Wrap_Struct(self, 0, free, f); return info; } and I change the method declaration in Init to be the following: rb_define_method(rb_cTest, "initialize", foo_new, 0); Now, when I do what I did before, I get an error: b = Bar.new f = Test.new b.test(f) // TypeError: wrong argument type Test (expected Data) Any idea why trying to define a constructor rather than a 'factory' method is causing me issues? -- Thanks in advance! Bryan On Mon, May 5, 2008 at 12:48 PM, Bryan Richardson wrote: > Jan, > > Awesome... this now works perfectly! Also, thanks for the heads-up on > having to return a value and using Qnil. I was getting a segmentation > fault > in irb that I wasn't sure about and it was because I wasn't returning > anything. > > One side question... why is it called 'Qnil'? What is the 'Q' for? > > -- > Thanks again! > Bryan > > On Mon, May 5, 2008 at 10:38 AM, Jan Dvorak wrote: > > > On Monday 05 May 2008 15:44:03 Bryan Richardson wrote: > > > Hi Jan, > > > > > > Alright, that makes sense, thanks for the information. However, that > > > doesn't help me to understand how I can pass a Ruby array of objects > to > > the > > > execute method. Am I missing something here? Can you help me with > > this? > > > > > The array is just an object (everything in ruby is object) which you can > > manipulate from C with rb_ary_* functions. You wrote the code yourself: > > > > VALUE foo = rb_ary_entry(foos, 0); // this will return the first > element > > of > > the array > > > > now, rb_* functions operate on (and returns) ruby objects (VALUE), if > you > > want > > to direclty use POD data types in C, you have to convert them, e.g. : > > > > VALUE val = rb_iv_get(foo,"@value"); > > printf("Foo Value: %i\n", NUM2INT(val)); > > > > or alternatively > > > > printf("Foo Value: %i\n", NUM2INT(rb_iv_get(foo, "@value")); > > > > For integral types there are general macros INT2NUM (c to ruby) and > > NUM2INT > > (ruby to C), and their variants (FIX2INT,INT2FIX,..), for floats/doubles > > there is NUM2DBL (ruby to c) and rb_float_new() (C to ruby). > > > > Also, every method in ruby must return value, so if your function does > not > > return anything, you have to explicitly return 'nil' with > > > > return Qnil; > > > > Jan > > > > > ------=_Part_21962_13270493.1210023708260--