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
--
Posted via http://www.ruby-forum.com/.

Bryan Richardson 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.

···

--
Posted via http://www.ruby-forum.com/\.

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

On 5/6/08, Albert Schlef <albertschlef@gmail.com> wrote:

Bryan Richardson 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.
--
Posted via http://www.ruby-forum.com/\.