Yet another question about extending ruby with C

  • Thread starter Bryan Richardson
  • Start date
B

Bryan Richardson

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?
 
A

Albert Schlef

Bryan said:
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.
 
B

btricha

Hi Albert,

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

--
Bryan

Bryan said:
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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top