From: Eero Saynatkari Date: 2005-12-13T17:08:20+09:00 Subject: Re: Accessing C structures in Ruby On 2005.12.13 16:42, Joe Van Dyk wrote: > On 12/12/05, Eero Saynatkari wrote: > > On 2005.12.13 14:14, Joe Van Dyk wrote: > > > On 12/12/05, Joe Van Dyk wrote: > > > > On 12/12/05, Eero Saynatkari 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? It does not :) There are just many ways you could achieve the same result --of which I consider this the best merely because of the simplicity. E