I do not think your speed problem is directly to do with calls to rb_iv_get
. You should first consider whether you need to keep the data in a Ruby object at all. It may be far more effective to have the data in a C data structure, and convert it to or from Ruby data as needed by methods your extension adds to the class.
However, if you need to manage a Ruby object as an integral part of a C extension, then you can keep the value as part of a C struct
and implement an accessor for the Ruby side to see it if necessary. Then you don't need to call rb_iv_get
at all to access the VALUE
in C.
First you will need to understand how to use Data_Wrap_Struct
and Data_Get_Struct
macros from ruby.h - the Extending Ruby chapter of Programming Ruby is a good place to see this in action, with the CD Jukebox example.
Then, armed with this, you can make one of your structure components a VALUE:
typedef struct my_structure {
int some_number;
VALUE some_ruby_val;
} MyStructure;
In addition to the CD Jukebox example, you will need to implement a function that marks some_ruby_val
as being in use (if you don't do this, Ruby's garbage collector will recycle the memory, and you could end up with some other object being pointed to - usually that will get you a segfault):
void my_structure_gc_mark( MyStructure *mine ) {
rb_gc_mark( mine->some_ruby_val );
return;
}
When you use Data_Wrap_Struct
, you tell it about this function, as well as the destroy function documented in the link:
Data_Wrap_Struct( klass, my_structure_gc_mark, my_structure_destroy, mine );
Ruby then takes care of calling it when necessary.
Finally, to get your extension-held Ruby data, you just unwrap the structure and refer it like any other part of a struct
. By way of example, here is how you would implement the accessor method for the above:
VALUE my_ext_get_some_ruby_val( VALUE self ) {
MyStructure *mine;
Data_Get_Struct( self, MyStructure, mine );
return mine->some_ruby_val;
}