Reputation: 720
I am trying to re-implement this Ruby method:
def reshape new_shape
t = reshape_clone_structure(new_shape)
left_params = [:*]*new_shape.size
right_params = [:*]*self.shape.size
t[*left_params] = self[*right_params]
t
end
As a C extension to a Ruby matrix library.
I am stuck on how to pass multiple values to []=
which is implemented in an existing C extension with this definition:
static VALUE nm_mset(int argc, VALUE* argv, VALUE self)
How do I translate the Ruby code t[*left_params] =
into C?
Upvotes: 0
Views: 128
Reputation: 27207
The nm_mset
method uses standard conventions for Ruby C extensions. The argc
variable is a an integer, specifying number of parameters being sent. Then argv
is a C array/pointer of type VALUE *
which must contain all the Ruby-ish parameters (for an assignment, the last of these params is the value of the right hand side). Thirdly self
is the Ruby Object receiver - but do remember that this might be either the class or an instance of it depending on how the method has been defined for Ruby.
To call it, you need to construct a VALUE *
array with each parameter a VALUE
, sent in the correct order.
I think you want to do something like this:
// Assuming you have following values already processed
// Assignments are not shown here - that is work for you!
VALUE self;
VALUE t;
int self_size;
int new_size;
//////////////////////////////////////////////////////////////////
//
// Assuming you set above values correctly, the following should
// work.
int i;
// Get reference to :*
VALUE asterisk = ID2SYM( rb_intern("*") );
// NB +1, we need to add call to self[ *right_params ] to end later
VALUE *left_params = ALLOC_N( VALUE, new_size + 1 );
for(i=0;i<new_size;i++) { left_params[i] = asterisk; }
VALUE *right_params = ALLOC_N( VALUE, self_size );
for(i=0;i<self_size;i++) { right_params[i] = asterisk; }
// equivalent to self[ *right_params ],
// but we push it straight into end of left_params ready for next step
left_params[ new_size ] = nm_mget( self_size, right_params, self );
// equivalent to t[ *left_params ] =
// Note +1 to size again, the last item is the value to assign
nm_mset( new_size + 1, left_params, t );
// Tidy up
xfree( left_params );
xfree( right_params );
return t;
Upvotes: 1
Reputation: 1667
it is doeable in C , first you need to include the header <stdarg.h>
then set the function to be like this
type function(type argument , ...){}
after that use the variable type va_list
and the three functions va_start
, va_end
and va_arg
to "navigate" trought the arguments as shown here
Upvotes: 0