Delayed initialization with alloc_function

Hello guys, I am wrapping a C++ library and after changing from define
singleton method "new" to alloc function and initialize, I ran into this
problem, imagine the classes are like those:

class MyOtherClass
{
public:
MyOtherClass(int a, int b);
private:
int a;
int b;
}

class MyClass
{
public:
MyClass(int a, int b);
MyOtherClass myFunc(int c);
private:
int a;
int b;
};

1.- in alloc function, I have to create a MyClass object and wrap it with
Data_Wrap_Struct, but I cant create an object at that time, because I have no
constructor parameter until initialize (and I dont have a default constructor
either). How do I solve this?
2.- If class MyClass func returns a MyOther class object, whats the best way
to wrap this?, I have even a function that returns a collection of
MyOtherClass objects, so I think I have to iterate trough it, and create a
ruby wrapped object not from scratch but wrapping the current object in the
collection, and then add all the ruby objects to a Ruby array, in this case,
whats the best way to wrap it?

Thanks for the help guys!

Duncan

Duncan Mac-Vicar Prett wrote:

Hello guys, I am wrapping a C++ library and after changing from define
singleton method "new" to alloc function and initialize, I ran into this
problem, imagine the classes are like those:

class MyOtherClass
{
public:
        MyOtherClass(int a, int b);
private:
        int a;
        int b;
}

class MyClass
{
public:
        MyClass(int a, int b);
        MyOtherClass myFunc(int c);
private:
        int a;
        int b;
};

1.- in alloc function, I have to create a MyClass object and wrap it with
Data_Wrap_Struct, but I cant create an object at that time, because I have no
constructor parameter until initialize (and I dont have a default constructor
either). How do I solve this?
2.- If class MyClass func returns a MyOther class object, whats the best way
to wrap this?, I have even a function that returns a collection of
MyOtherClass objects, so I think I have to iterate trough it, and create a
ruby wrapped object not from scratch but wrapping the current object in the
collection, and then add all the ruby objects to a Ruby array, in this case,
whats the best way to wrap it?

Thanks for the help guys!

Duncan

You have two options:
1) Don't use an alloc/initialize and instead override 'new'. This is
simple, but it does not follow the ruby way, nor does it allow your
class to be subclassed.
2) Make a dummy alloc function, then do all the work in initialize.
(This is my preference.)
Your alloc function would look like:
VALUE
my_alloc(VALUE klass) {
  return Data_Wrap_Struct(klass, NULL, NULL, NULL);
}
and your initialize function like:
VALUE
my_init(int argc, VALUE *argv, VALUE self)
{
  MyOtherClass *p;
  /* handle args, create and initialize MyOtherClass instance */
  RDATA(self)->dmark = my_mark_function;
  RDATA(self)->dfree = my_free_function;
  RDATA(self)->data = p;
  return self;
}
You also should check RDATA(self)->data != NULL in all your methods.
This is easy though:
#define GetMyOtherClass(obj, var) do { \
  Data_Get_Struct(obj, MyOtherClass, var); \
  if ((var) == NULL) rb_raise(rb_eFatal, "you never initialized me"); \
} while (0)

You may also want to define a replace function (see array.c or
string.c).

--I am not much of a C++ programmer, so syntax may be wrong--

-Charlie