0

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?

7
  • Are you familiar with printf? Commented Feb 18, 2014 at 17:55
  • yes but i dont see how to do it i need t [:*,:*...'size' no of times] Commented Feb 18, 2014 at 18:02
  • Could you give a little more context? There is no function definition (either Ruby or C) in the question - it may help a lot to show that. I have written functions which take variable numbers of param in Ruby and as C extensions for gems, and I have never seen the syntax in your question (in fact I have no idea what it does!) Commented Feb 18, 2014 at 19:57
  • heres the definition github.com/SciRuby/nmatrix/blob/master/lib/nmatrix/… Commented Feb 18, 2014 at 20:39
  • basically the symbols indicate to use full range,the new_shape.size varies,so no. of args vary for diff. cases . i need to do this in c ext. Commented Feb 18, 2014 at 20:41

2 Answers 2

1

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;
Sign up to request clarification or add additional context in comments.

1 Comment

I think i will have to use the libraries alloc , but it works cleanly. I will make sure i am clearer in next questions. The way you explained the workaround is great.
0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.