Bryan Richardson
5/5/2008 9:42:00 PM
[Note: parts of this message were removed to make it a legal post.]
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 <btricha@gmail.com> 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 <jan.dvorak@kraxnet.cz> 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
> >
> >
>