在 C 中构造参数以调用具有可变参数数的 Ruby C 扩展



我正在尝试重新实现这个Ruby方法:

  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

作为 Ruby 矩阵库的 C 扩展。

我坚持如何将多个值传递给[]=这是在具有以下定义的现有 C 扩展中实现的:

static VALUE nm_mset(int argc, VALUE* argv, VALUE self)

如何将 Ruby 代码t[*left_params] =转换为 C?

nm_mset 方法使用 Ruby C 扩展的标准约定。argc变量是一个整数,指定要发送的参数数。然后argv是一个类型为 VALUE * 的 C 数组/指针,它必须包含所有Ruby-ish 参数(对于赋值,这些参数中的最后一个是右侧的值)。第三self是 Ruby 对象接收器 - 但请记住,这可能是类或它的实例,具体取决于如何为 Ruby 定义方法。

要调用它,您需要构造一个VALUE *数组,每个参数都是一个VALUE,以正确的顺序发送。

我想你想做这样的事情:

// 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;

它在 C 中是可以做的,首先你需要包含标头<stdarg.h>然后将函数设置为如下所示

type function(type argument , ...){}

之后使用变量类型va_list和三个函数va_startva_endva_arg来"导航"参数,如下所示

最新更新