Yet another question about extending ruby with C

Hello all,

I’m still working on figuring how how to extend ruby with C libraries.
Hope someone can help me with this one!

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

Bryan R. wrote:

Say I have the following:

typedef struct {
char* name;
} Foo;

[…]

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;
}

[…]

If I do the following, everything works perfectly and I see my name
printed
on the screen:

[…]
b.test(f) // prints “Bryan”

“works perfectly”? I don’t see how it can print “Bryan”, for two
reasons:

  1. It’s supposed to print “Name: Bryan”, not “Bryan”.

  2. But it can’t print “Name: Bryan” either. That’s because in foo_init()
    you aren’t settings f->name to “Bryan”. Instead, you’re settings an
    instance variable, “@name”, to “Bryan”. It happens that “@name” has a
    similar name to char *name, but these two variables aren’t related at
    all.

Last but not least:

If you want ppl to help you, you must make it easier for them to help
you. Do that by choosing sane names for your
methods/structures/variables. I had a hard time following your code (and
that in your previous question). ‘test’, ‘Test’ and ‘Foo’ aren’t
meaningful names. Change them to make_person, Person, and person_rec.

Hi Albert,

Thanks for responding. Sorry for not making things clear and easy to
follow… I was in a hurry when I wrote it. :confused: I’ll try and clear
things up when I have a chance. Thanks again!


Bryan

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs