Accessing C structures in Ruby

(I've already looked at Swig, btw. I'd like to do this one by hand.)

I have the following:

typedef struct {
  double x;
  double y;
  double z;
} VelocityRecord;

typedef struct {
  double x;
  double y;
  double z;
} PositionRecord;

typedef struct {
  int id;
  int type;
  PositionRecord position;
  VelocityRecord velocity;
} Player;

Player Players[10];

The number of Players is fixed ahead of time. I want to be able to
access that data from Ruby. Ideally, something like:

module Simulation
    attr_accessor :players # Other stuff will be here
    class Player
        class VelocityRecord
            attr_accessor :x, :y :z
        end
        class PositionRecord
          attr_accessor :x, :y, :z
        end
    end
end

Hm, on second thought, it's probably a lot easier to do:

class Player
  attr_reader :x_position, :y_position, :z_position, :x_velocity,
:y_velocity, :z_velocity
end

So, maybe something like this?

void Init_Simulation()
{
  rb_define_module(mSimulation, "Simulation");
  rb_define_class_under(cPlayer, "Player");

  rb_define_method(cPlayer, "x_position", get_x_position, 0);
  rb_define_method(cPlayer, "y_position", get_y_position, 0);
  rb_define_method(cPlayer, "z_position", get_z_position, 0);
  rb_define_method(cPlayer, "x_velocity", get_x_velocity, 0);
  rb_define_method(cPlayer, "y_velocity", get_y_velocity, 0);
  rb_define_method(cPlayer, "z_velocity", get_z_velocity, 0);
}

···

On 12/12/05, Joe Van Dyk <joevandyk@gmail.com> wrote:

(I've already looked at Swig, btw. I'd like to do this one by hand.)

I have the following:

typedef struct {
  double x;
  double y;
  double z;
} VelocityRecord;

typedef struct {
  double x;
  double y;
  double z;
} PositionRecord;

typedef struct {
  int id;
  int type;
  PositionRecord position;
  VelocityRecord velocity;
} Player;

Player Players[10];

The number of Players is fixed ahead of time. I want to be able to
access that data from Ruby. Ideally, something like:

module Simulation
    attr_accessor :players # Other stuff will be here
    class Player
        class VelocityRecord
            attr_accessor :x, :y :z
        end
        class PositionRecord
          attr_accessor :x, :y, :z
        end
    end
end

Joe Van Dyk wrote:

(I've already looked at Swig, btw. I'd like to do this one by hand.)

I have the following:

typedef struct {
  double x;
  double y;
  double z;
} VelocityRecord;

typedef struct {
  double x;
  double y;
  double z;
} PositionRecord;

typedef struct {
  int id;
  int type;
  PositionRecord position;
  VelocityRecord velocity;
} Player;

Player Players[10];

The number of Players is fixed ahead of time. I want to be able to
access that data from Ruby. Ideally, something like:

module Simulation
    attr_accessor :players # Other stuff will be here
    class Player
        class VelocityRecord
            attr_accessor :x, :y :z
        end
        class PositionRecord
          attr_accessor :x, :y, :z
        end
    end
end

My typical recommendation is to just wrap a pointer to
the struct and pass that around. Then, for each method
just extract the pointer, access the correct field and
generate a VALUE out of that (inside the function that
corresponds to the method).

E

···

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

So, I have a bunch of functions that look like this now:

VALUE get_player_x_pos(VALUE self)
{
  Player* p;
  Data_Get_Struct(self, Player, p);
   rb_float_new(p->position.x);
}

That the way to go?

···

On 12/12/05, Joe Van Dyk <joevandyk@gmail.com> wrote:

On 12/12/05, Joe Van Dyk <joevandyk@gmail.com> wrote:
> (I've already looked at Swig, btw. I'd like to do this one by hand.)
>
> I have the following:
>
> typedef struct {
> double x;
> double y;
> double z;
> } VelocityRecord;
>
> typedef struct {
> double x;
> double y;
> double z;
> } PositionRecord;
>
> typedef struct {
> int id;
> int type;
> PositionRecord position;
> VelocityRecord velocity;
> } Player;
>
> Player Players[10];
>
>
> The number of Players is fixed ahead of time. I want to be able to
> access that data from Ruby. Ideally, something like:
>
> module Simulation
> attr_accessor :players # Other stuff will be here
> class Player
> class VelocityRecord
> attr_accessor :x, :y :z
> end
> class PositionRecord
> attr_accessor :x, :y, :z
> end
> end
> end

Hm, on second thought, it's probably a lot easier to do:

class Player
  attr_reader :x_position, :y_position, :z_position, :x_velocity,
:y_velocity, :z_velocity
end

So, maybe something like this?

void Init_Simulation()
{
  rb_define_module(mSimulation, "Simulation");
  rb_define_class_under(cPlayer, "Player");

  rb_define_method(cPlayer, "x_position", get_x_position, 0);
  rb_define_method(cPlayer, "y_position", get_y_position, 0);
  rb_define_method(cPlayer, "z_position", get_z_position, 0);
  rb_define_method(cPlayer, "x_velocity", get_x_velocity, 0);
  rb_define_method(cPlayer, "y_velocity", get_y_velocity, 0);
  rb_define_method(cPlayer, "z_velocity", get_z_velocity, 0);
}

Can you share more details? Is that essentially what I've done in my
later posts on this?

···

On 12/12/05, Eero Saynatkari <ruby-forum-reg@mailinator.com> wrote:

Joe Van Dyk wrote:
> (I've already looked at Swig, btw. I'd like to do this one by hand.)
>
> I have the following:
>
> typedef struct {
> double x;
> double y;
> double z;
> } VelocityRecord;
>
> typedef struct {
> double x;
> double y;
> double z;
> } PositionRecord;
>
> typedef struct {
> int id;
> int type;
> PositionRecord position;
> VelocityRecord velocity;
> } Player;
>
> Player Players[10];
>
>
> The number of Players is fixed ahead of time. I want to be able to
> access that data from Ruby. Ideally, something like:
>
> module Simulation
> attr_accessor :players # Other stuff will be here
> class Player
> class VelocityRecord
> attr_accessor :x, :y :z
> end
> class PositionRecord
> attr_accessor :x, :y, :z
> end
> end
> end

My typical recommendation is to just wrap a pointer to
the struct and pass that around. Then, for each method
just extract the pointer, access the correct field and
generate a VALUE out of that (inside the function that
corresponds to the method).

Here's what I have so far. Seems to work well:

#include "ruby.h"
#include "simulation.h"

VALUE get_frame_count(VALUE self) { return INT2NUM(HIFEN2_Count); }
VALUE get_mission_time(VALUE self) { return INT2NUM(HIFEN2_Mission); }
VALUE get_max_players(VALUE self) { return INT2NUM(MAX_PLAYERS); }

VALUE player_new(VALUE self, VALUE rb_i)
{
  int i = NUM2INT(rb_i);
  return Data_Wrap_Struct(self, NULL, NULL, &Players[i]);
}

Player* get_player(VALUE self)
{
  Player *p;
  Data_Get_Struct(self, Player, p);
  return p;
}

VALUE get_player_id(VALUE self) { return INT2NUM(get_player(self)->id); }

VALUE get_player_x_pos(VALUE self) { return
rb_float_new(get_player(self)->position.x); }
VALUE get_player_y_pos(VALUE self) { return
rb_float_new(get_player(self)->position.y); }
VALUE get_player_z_pos(VALUE self) { return
rb_float_new(get_player(self)->position.z); }

VALUE get_player_x_vel(VALUE self) { return
rb_float_new(get_player(self)->velocity.x); }
VALUE get_player_y_vel(VALUE self) { return
rb_float_new(get_player(self)->velocity.y); }
VALUE get_player_z_vel(VALUE self) { return
rb_float_new(get_player(self)->velocity.z); }

VALUE cSimulation;
VALUE cPlayer;

void Init_Sim()
{
  cSimulation = rb_define_class("Simulation", rb_cObject);
  rb_define_method(cSimulation, "frame_count", get_frame_count, 0);
  rb_define_method(cSimulation, "mission_time", get_mission_time, 0);
  rb_define_method(cSimulation, "max_players", get_max_players, 0);

  cPlayer = rb_define_class("Player", rb_cObject);
  rb_define_singleton_method(cPlayer, "new", player_new, 1);
  rb_define_method(cPlayer, "player_id", get_player_id, 0);

  rb_define_method(cPlayer, "x_position", get_player_x_pos, 0);
  rb_define_method(cPlayer, "y_position", get_player_y_pos, 0);
  rb_define_method(cPlayer, "z_position", get_player_z_pos, 0);

  rb_define_method(cPlayer, "x_velocity", get_player_x_vel, 0);
  rb_define_method(cPlayer, "y_velocity", get_player_y_vel, 0);
  rb_define_method(cPlayer, "z_velocity", get_player_z_vel, 0);
}

···

On 12/12/05, Joe Van Dyk <joevandyk@gmail.com> wrote:

On 12/12/05, Eero Saynatkari <ruby-forum-reg@mailinator.com> wrote:
> Joe Van Dyk wrote:
> > (I've already looked at Swig, btw. I'd like to do this one by hand.)
> >
> > I have the following:
> >
> > typedef struct {
> > double x;
> > double y;
> > double z;
> > } VelocityRecord;
> >
> > typedef struct {
> > double x;
> > double y;
> > double z;
> > } PositionRecord;
> >
> > typedef struct {
> > int id;
> > int type;
> > PositionRecord position;
> > VelocityRecord velocity;
> > } Player;
> >
> > Player Players[10];
> >
> >
> > The number of Players is fixed ahead of time. I want to be able to
> > access that data from Ruby. Ideally, something like:
> >
> > module Simulation
> > attr_accessor :players # Other stuff will be here
> > class Player
> > class VelocityRecord
> > attr_accessor :x, :y :z
> > end
> > class PositionRecord
> > attr_accessor :x, :y, :z
> > end
> > end
> > end
>
> My typical recommendation is to just wrap a pointer to
> the struct and pass that around. Then, for each method
> just extract the pointer, access the correct field and
> generate a VALUE out of that (inside the function that
> corresponds to the method).

Can you share more details? Is that essentially what I've done in my
later posts on this?

Yep, that looks fine to me. There are certainly other ways but aside
from some repetitiveness, this is easy and versatile (particularly if
you need to pass data to C libraries as well). If you have lots and
lots of functions like that, you could even do with a little #define.

E

···

On 2005.12.13 14:14, Joe Van Dyk <joevandyk@gmail.com> wrote:

On 12/12/05, Joe Van Dyk <joevandyk@gmail.com> wrote:
> On 12/12/05, Eero Saynatkari <ruby-forum-reg@mailinator.com> wrote:
> > Joe Van Dyk wrote:
> > > (I've already looked at Swig, btw. I'd like to do this one by hand.)
> > >
> > > I have the following:
> > >
> > > typedef struct {
> > > double x;
> > > double y;
> > > double z;
> > > } VelocityRecord;
> > >
> > > typedef struct {
> > > double x;
> > > double y;
> > > double z;
> > > } PositionRecord;
> > >
> > > typedef struct {
> > > int id;
> > > int type;
> > > PositionRecord position;
> > > VelocityRecord velocity;
> > > } Player;
> > >
> > > Player Players[10];
> > >
> > >
> > > The number of Players is fixed ahead of time. I want to be able to
> > > access that data from Ruby. Ideally, something like:
> > >
> > > module Simulation
> > > attr_accessor :players # Other stuff will be here
> > > class Player
> > > class VelocityRecord
> > > attr_accessor :x, :y :z
> > > end
> > > class PositionRecord
> > > attr_accessor :x, :y, :z
> > > end
> > > end
> > > end
> >
> > My typical recommendation is to just wrap a pointer to
> > the struct and pass that around. Then, for each method
> > just extract the pointer, access the correct field and
> > generate a VALUE out of that (inside the function that
> > corresponds to the method).
>
> Can you share more details? Is that essentially what I've done in my
> later posts on this?

Here's what I have so far. Seems to work well:

#include "ruby.h"
#include "simulation.h"

VALUE get_frame_count(VALUE self) { return INT2NUM(HIFEN2_Count); }
VALUE get_mission_time(VALUE self) { return INT2NUM(HIFEN2_Mission); }
VALUE get_max_players(VALUE self) { return INT2NUM(MAX_PLAYERS); }

VALUE player_new(VALUE self, VALUE rb_i)
{
  int i = NUM2INT(rb_i);
  return Data_Wrap_Struct(self, NULL, NULL, &Players[i]);
}

Player* get_player(VALUE self)
{
  Player *p;
  Data_Get_Struct(self, Player, p);
  return p;
}

VALUE get_player_id(VALUE self) { return INT2NUM(get_player(self)->id); }

VALUE get_player_x_pos(VALUE self) { return
rb_float_new(get_player(self)->position.x); }
VALUE get_player_y_pos(VALUE self) { return
rb_float_new(get_player(self)->position.y); }
VALUE get_player_z_pos(VALUE self) { return
rb_float_new(get_player(self)->position.z); }

VALUE get_player_x_vel(VALUE self) { return
rb_float_new(get_player(self)->velocity.x); }
VALUE get_player_y_vel(VALUE self) { return
rb_float_new(get_player(self)->velocity.y); }
VALUE get_player_z_vel(VALUE self) { return
rb_float_new(get_player(self)->velocity.z); }

VALUE cSimulation;
VALUE cPlayer;

void Init_Sim()
{
  cSimulation = rb_define_class("Simulation", rb_cObject);
  rb_define_method(cSimulation, "frame_count", get_frame_count, 0);
  rb_define_method(cSimulation, "mission_time", get_mission_time, 0);
  rb_define_method(cSimulation, "max_players", get_max_players, 0);

  cPlayer = rb_define_class("Player", rb_cObject);
  rb_define_singleton_method(cPlayer, "new", player_new, 1);
  rb_define_method(cPlayer, "player_id", get_player_id, 0);

  rb_define_method(cPlayer, "x_position", get_player_x_pos, 0);
  rb_define_method(cPlayer, "y_position", get_player_y_pos, 0);
  rb_define_method(cPlayer, "z_position", get_player_z_pos, 0);

  rb_define_method(cPlayer, "x_velocity", get_player_x_vel, 0);
  rb_define_method(cPlayer, "y_velocity", get_player_y_vel, 0);
  rb_define_method(cPlayer, "z_velocity", get_player_z_vel, 0);
}

How does my code differ from what you described?

···

On 12/12/05, Eero Saynatkari <ruby-ml@magical-cat.org> wrote:

On 2005.12.13 14:14, Joe Van Dyk <joevandyk@gmail.com> wrote:
> On 12/12/05, Joe Van Dyk <joevandyk@gmail.com> wrote:
> > On 12/12/05, Eero Saynatkari <ruby-forum-reg@mailinator.com> wrote:
> > > Joe Van Dyk wrote:
> > > > (I've already looked at Swig, btw. I'd like to do this one by hand.)
> > > >
> > > > I have the following:
> > > >
> > > > typedef struct {
> > > > double x;
> > > > double y;
> > > > double z;
> > > > } VelocityRecord;
> > > >
> > > > typedef struct {
> > > > double x;
> > > > double y;
> > > > double z;
> > > > } PositionRecord;
> > > >
> > > > typedef struct {
> > > > int id;
> > > > int type;
> > > > PositionRecord position;
> > > > VelocityRecord velocity;
> > > > } Player;
> > > >
> > > > Player Players[10];
> > > >
> > > >
> > > > The number of Players is fixed ahead of time. I want to be able to
> > > > access that data from Ruby. Ideally, something like:
> > > >
> > > > module Simulation
> > > > attr_accessor :players # Other stuff will be here
> > > > class Player
> > > > class VelocityRecord
> > > > attr_accessor :x, :y :z
> > > > end
> > > > class PositionRecord
> > > > attr_accessor :x, :y, :z
> > > > end
> > > > end
> > > > end
> > >
> > > My typical recommendation is to just wrap a pointer to
> > > the struct and pass that around. Then, for each method
> > > just extract the pointer, access the correct field and
> > > generate a VALUE out of that (inside the function that
> > > corresponds to the method).
> >
> > Can you share more details? Is that essentially what I've done in my
> > later posts on this?
>
> Here's what I have so far. Seems to work well:
>
> #include "ruby.h"
> #include "simulation.h"
>
> VALUE get_frame_count(VALUE self) { return INT2NUM(HIFEN2_Count); }
> VALUE get_mission_time(VALUE self) { return INT2NUM(HIFEN2_Mission); }
> VALUE get_max_players(VALUE self) { return INT2NUM(MAX_PLAYERS); }
>
> VALUE player_new(VALUE self, VALUE rb_i)
> {
> int i = NUM2INT(rb_i);
> return Data_Wrap_Struct(self, NULL, NULL, &Players[i]);
> }
>
> Player* get_player(VALUE self)
> {
> Player *p;
> Data_Get_Struct(self, Player, p);
> return p;
> }
>
> VALUE get_player_id(VALUE self) { return INT2NUM(get_player(self)->id); }
>
> VALUE get_player_x_pos(VALUE self) { return
> rb_float_new(get_player(self)->position.x); }
> VALUE get_player_y_pos(VALUE self) { return
> rb_float_new(get_player(self)->position.y); }
> VALUE get_player_z_pos(VALUE self) { return
> rb_float_new(get_player(self)->position.z); }
>
> VALUE get_player_x_vel(VALUE self) { return
> rb_float_new(get_player(self)->velocity.x); }
> VALUE get_player_y_vel(VALUE self) { return
> rb_float_new(get_player(self)->velocity.y); }
> VALUE get_player_z_vel(VALUE self) { return
> rb_float_new(get_player(self)->velocity.z); }
>
> VALUE cSimulation;
> VALUE cPlayer;
>
> void Init_Sim()
> {
> cSimulation = rb_define_class("Simulation", rb_cObject);
> rb_define_method(cSimulation, "frame_count", get_frame_count, 0);
> rb_define_method(cSimulation, "mission_time", get_mission_time, 0);
> rb_define_method(cSimulation, "max_players", get_max_players, 0);
>
> cPlayer = rb_define_class("Player", rb_cObject);
> rb_define_singleton_method(cPlayer, "new", player_new, 1);
> rb_define_method(cPlayer, "player_id", get_player_id, 0);
>
> rb_define_method(cPlayer, "x_position", get_player_x_pos, 0);
> rb_define_method(cPlayer, "y_position", get_player_y_pos, 0);
> rb_define_method(cPlayer, "z_position", get_player_z_pos, 0);
>
> rb_define_method(cPlayer, "x_velocity", get_player_x_vel, 0);
> rb_define_method(cPlayer, "y_velocity", get_player_y_vel, 0);
> rb_define_method(cPlayer, "z_velocity", get_player_z_vel, 0);
> }

Yep, that looks fine to me. There are certainly other ways but aside
from some repetitiveness, this is easy and versatile (particularly if
you need to pass data to C libraries as well). If you have lots and
lots of functions like that, you could even do with a little #define.

CGenerator might be helpful (not used it
myself, but this seems like a prime use case)

martin

···

Eero Saynatkari <ruby-ml@magical-cat.org> wrote:

Yep, that looks fine to me. There are certainly other ways but aside
from some repetitiveness, this is easy and versatile (particularly if
you need to pass data to C libraries as well). If you have lots and
lots of functions like that, you could even do with a little #define.

It does not :slight_smile: There are just many ways you could achieve the same
result --of which I consider this the best merely because of the
simplicity.

E

···

On 2005.12.13 16:42, Joe Van Dyk <joevandyk@gmail.com> wrote:

On 12/12/05, Eero Saynatkari <ruby-ml@magical-cat.org> wrote:
> On 2005.12.13 14:14, Joe Van Dyk <joevandyk@gmail.com> wrote:
> > On 12/12/05, Joe Van Dyk <joevandyk@gmail.com> wrote:
> > > On 12/12/05, Eero Saynatkari <ruby-forum-reg@mailinator.com> wrote:
> > > > Joe Van Dyk wrote:
> > > > > (I've already looked at Swig, btw. I'd like to do this one by hand.)
> > > > >
> > > > > I have the following:
> > > > >
> > > > > typedef struct {
> > > > > double x;
> > > > > double y;
> > > > > double z;
> > > > > } VelocityRecord;
> > > > >
> > > > > typedef struct {
> > > > > double x;
> > > > > double y;
> > > > > double z;
> > > > > } PositionRecord;
> > > > >
> > > > > typedef struct {
> > > > > int id;
> > > > > int type;
> > > > > PositionRecord position;
> > > > > VelocityRecord velocity;
> > > > > } Player;
> > > > >
> > > > > Player Players[10];
> > > > >
> > > > >
> > > > > The number of Players is fixed ahead of time. I want to be able to
> > > > > access that data from Ruby. Ideally, something like:
> > > > >
> > > > > module Simulation
> > > > > attr_accessor :players # Other stuff will be here
> > > > > class Player
> > > > > class VelocityRecord
> > > > > attr_accessor :x, :y :z
> > > > > end
> > > > > class PositionRecord
> > > > > attr_accessor :x, :y, :z
> > > > > end
> > > > > end
> > > > > end
> > > >
> > > > My typical recommendation is to just wrap a pointer to
> > > > the struct and pass that around. Then, for each method
> > > > just extract the pointer, access the correct field and
> > > > generate a VALUE out of that (inside the function that
> > > > corresponds to the method).
> > >
> > > Can you share more details? Is that essentially what I've done in my
> > > later posts on this?
> >
> > Here's what I have so far. Seems to work well:
> >
> > #include "ruby.h"
> > #include "simulation.h"
> >
> > VALUE get_frame_count(VALUE self) { return INT2NUM(HIFEN2_Count); }
> > VALUE get_mission_time(VALUE self) { return INT2NUM(HIFEN2_Mission); }
> > VALUE get_max_players(VALUE self) { return INT2NUM(MAX_PLAYERS); }
> >
> > VALUE player_new(VALUE self, VALUE rb_i)
> > {
> > int i = NUM2INT(rb_i);
> > return Data_Wrap_Struct(self, NULL, NULL, &Players[i]);
> > }
> >
> > Player* get_player(VALUE self)
> > {
> > Player *p;
> > Data_Get_Struct(self, Player, p);
> > return p;
> > }
> >
> > VALUE get_player_id(VALUE self) { return INT2NUM(get_player(self)->id); }
> >
> > VALUE get_player_x_pos(VALUE self) { return
> > rb_float_new(get_player(self)->position.x); }
> > VALUE get_player_y_pos(VALUE self) { return
> > rb_float_new(get_player(self)->position.y); }
> > VALUE get_player_z_pos(VALUE self) { return
> > rb_float_new(get_player(self)->position.z); }
> >
> > VALUE get_player_x_vel(VALUE self) { return
> > rb_float_new(get_player(self)->velocity.x); }
> > VALUE get_player_y_vel(VALUE self) { return
> > rb_float_new(get_player(self)->velocity.y); }
> > VALUE get_player_z_vel(VALUE self) { return
> > rb_float_new(get_player(self)->velocity.z); }
> >
> > VALUE cSimulation;
> > VALUE cPlayer;
> >
> > void Init_Sim()
> > {
> > cSimulation = rb_define_class("Simulation", rb_cObject);
> > rb_define_method(cSimulation, "frame_count", get_frame_count, 0);
> > rb_define_method(cSimulation, "mission_time", get_mission_time, 0);
> > rb_define_method(cSimulation, "max_players", get_max_players, 0);
> >
> > cPlayer = rb_define_class("Player", rb_cObject);
> > rb_define_singleton_method(cPlayer, "new", player_new, 1);
> > rb_define_method(cPlayer, "player_id", get_player_id, 0);
> >
> > rb_define_method(cPlayer, "x_position", get_player_x_pos, 0);
> > rb_define_method(cPlayer, "y_position", get_player_y_pos, 0);
> > rb_define_method(cPlayer, "z_position", get_player_z_pos, 0);
> >
> > rb_define_method(cPlayer, "x_velocity", get_player_x_vel, 0);
> > rb_define_method(cPlayer, "y_velocity", get_player_y_vel, 0);
> > rb_define_method(cPlayer, "z_velocity", get_player_z_vel, 0);
> > }
>
> Yep, that looks fine to me. There are certainly other ways but aside
> from some repetitiveness, this is easy and versatile (particularly if
> you need to pass data to C libraries as well). If you have lots and
> lots of functions like that, you could even do with a little #define.

How does my code differ from what you described?

Martin DeMello wrote:

Yep, that looks fine to me. There are certainly other ways but aside
from some repetitiveness, this is easy and versatile (particularly if
you need to pass data to C libraries as well). If you have lots and
lots of functions like that, you could even do with a little #define.

CGenerator might be helpful (not used it
myself, but this seems like a prime use case)

martin

I would have mentioned it but the OP wanted to do things the hard way :slight_smile:

Cgen takes care of accessors (including type checking/conversion, marshalling, mark/free when accessors are typed to refer to objects), and also manages inheritance of structure members in parallel with the ruby inheritance hierarchy. It's got a nice wrapper around rb_parse_args. It's also good if you want to dynamically generate the extension in response to loaded code, user input, etc. I've been using it for over 4 years now. The docs need work, though...

An example (simplified from http://redshift.sourceforge.net/cgen/examples/complex.rb.html\):

require 'cgen/cshadow'

class MyComplex < Numeric
   include CShadow
   shadow_attr_accessor :re => "double re", :im => "double im"
end

MyComplex.commit

z = MyComplex.new
z.re = 5
z.im = 1.3
p z

__END__

Output:

#<MyComplex:0x2b04630 im=1.3, re=5.0>

The full example also shows how to add methods written in C (but embedded in your ruby source) to do abs() and in-place multiplication.

Running this example generates a directory with the following contents, which is used to build the extension (all of this happens during the commit call):

C:\ruby\prj\cgen\examples>ls -l MyComplex
total 220
-rw-rw-rw- 1 vjoel 0 45 2005-12-13 09:42 extconf.rb
-rw-rw-rw- 1 vjoel 0 150 2005-12-13 09:42 make.log
-rw-rw-rw- 1 vjoel 0 3619 2005-12-13 09:42 Makefile
-rw-rw-rw- 1 vjoel 0 25 2005-12-13 09:39 MyComplex-i386-mswin32.def
-rwxrwxrwx 1 vjoel 0 3589 2005-12-13 09:39 MyComplex.c
-rw-rw-rw- 1 vjoel 0 589 2005-12-13 09:40 MyComplex.exp
-rw-rw-rw- 1 vjoel 0 762 2005-12-13 09:39 MyComplex.h
-rw-rw-rw- 1 vjoel 0 1976 2005-12-13 09:40 MyComplex.lib
-rw-rw-rw- 1 vjoel 0 17259 2005-12-13 09:39 MyComplex.obj
-rw-rw-rw- 1 vjoel 0 91136 2005-12-13 09:40 MyComplex.pdb
-rw-rw-rw- 1 vjoel 0 20546 2005-12-13 09:40 MyComplex.so
-rw-rw-rw- 1 vjoel 0 53248 2005-12-13 09:39 vc60.pdb

Cgen is careful not to repeat all this work the second time you run the same program--it writes files only if they have changed.

And just to give an idea of what functions it handles:

C:\ruby\prj\cgen\examples\MyComplex>grep "^\w" MyComplex.c
static void mark_MyComplex_Shadow(MyComplex_Shadow *shadow);
static void free_MyComplex_Shadow(MyComplex_Shadow *shadow);
VALUE module_MyComplex;
void Init_MyComplex(void)
static void mark_MyComplex_Shadow(MyComplex_Shadow *shadow)
static void free_MyComplex_Shadow(MyComplex_Shadow *shadow)
VALUE __dump__data_module_MyComplex_method(VALUE self)
VALUE __load__data_module_MyComplex_method(VALUE self, VALUE from_array)
VALUE im_module_MyComplex_method(VALUE self)
VALUE im_equals_module_MyComplex_method(int argc, VALUE *argv, VALUE self)
VALUE re_module_MyComplex_method(VALUE self)
VALUE re_equals_module_MyComplex_method(int argc, VALUE *argv, VALUE self)
VALUE new_module_MyComplex_singleton_method(int argc, VALUE *argv, VALUE self)
VALUE alloc_func_module_MyComplex(VALUE klass)

Here's an example (sample.rb) showing the argument parsing wrapper:

lib2.define_c_singleton_method(Point, :test).instance_eval {
   c_array_args {
     required :arg0, :arg1
     optional :arg2, :arg3, :arg4
     typecheck :arg2 => Numeric, :arg3 => Numeric
     default :arg3 => "INT2NUM(7)",
               :arg4 => "INT2NUM(NUM2INT(arg2) + NUM2INT(arg3))"
     rest :rest
     block :block
   }
   body %{\
     rb_funcall(block, #{declare_symbol :call}, 6,
                arg0, arg1, arg2, arg3, arg4, rest);
   }
}

···

Eero Saynatkari <ruby-ml@magical-cat.org> wrote:

--
        vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407