【问题标题】:Ruby C API - From ruby array to C arrayRuby C API - 从 ruby​​ 数组到 C 数组
【发布时间】:2016-05-10 18:36:49
【问题描述】:

我将一个数组(矩阵)从 Ruby 传递给一个 C 函数。目前我正在使用以下代码

VALUE matmat_mul(VALUE self, VALUE matrixA, VALUE matrixB)
{
    int rowsA = RARRAY_LEN(matrixA);
    VALUE firstElement = rb_ary_entry(matrixA, 0);
    int colsA = RARRAY_LEN(firstElement);
    int rowsB = RARRAY_LEN(matrixB);
    firstElement = rb_ary_entry(matrixB, 0);
    int colsB = RARRAY_LEN(firstElement);

    int i,j;
    double *matA = (double *)malloc(rowsA * colsA * sizeof(double));
    double *matB = (double *)malloc(rowsB * colsB * sizeof(double));

    VALUE rowA;
    for (i=0; i<rowsA; i++)
    {
        rowA = rb_ary_entry(matrixA, i);
        for (j=0; j<colsA; j++)
        {
            matA[i * colsA + j] = NUM2DBL(rb_ary_entry( rowA, j));
        }
    }

    //  same for matrix B
    ....
    ....

    // Perform operation C = A x B

    VALUE matrixC = rb_ary_new2(rowsC);
    VALUE rowC;
     for (i=0; i<rowsC; i++) {
         rowC = rb_ary_new2(colsC);
         for (j=0; j<colsC; j++) {
              rb_ary_store(rowC, j, DBL2NUM(matC[i * colsC + j]));
         }
         rb_ary_store(matrixC, i, rowC);
     }


return matrixC
}

有没有更好/更快的方法将 Ruby 数组转换为 C 数组,反之亦然?

【问题讨论】:

    标签: c arrays ruby ruby-c-extension


    【解决方案1】:

    不,没有更快的方法将 Ruby Array 转换为 C 结构。这是因为 Ruby Array 可以包含任何其他类型的 Ruby 对象的混合,其中许多无法转换为 C double

    还有另一个选择 - NArray。这是在 Ruby 中处理数值多维数组的一种非常有效的方法。从 NArray 转换为 C 的过程要少得多,但它是完全不同的做事方式。

    其中一些有点复杂。总之 。 . .

    在 extconf.rb 中加载 narray.h 库

    这个的原始版本来自 fftw3 gem(我已经简化了一点):

    require "mkmf"
    require "narray"
    
    narray_dir = File.dirname(Gem.find_files("narray.h").first) rescue $sitearchdir
    dir_config('narray', narray_dir, narray_dir)
    
    if ( ! ( have_header("narray.h") && have_header("narray_config.h") ) )
       puts "Header narray.h or narray_config.h is not found."
       exit(-1)
    end
    
    create_makefile( 'my_lib_name/my_lib_name' )
    

    将输入 NArray 对象转换为您要使用的数据类型

    这是一个可以访问 NArray 的示例实例方法

    VALUE example_narray_param( VALUE self, VALUE rv_narray ) {
      // Cast the input to the data type you want - here 32-bit ints
      volatile VALUE new_narray = na_cast_object(rv_narray, NA_LINT);
    
      // NARRAY is the C struct interface to NArray data
      struct NARRAY *na_items;
    
      // This macro is NArray's equivalent of NUM2DBL, pointing na_items 
      // at the data
      GetNArray( new_narray, na_items );
    
      // row now points natively to the data
      int * row = (int*) na_items->ptr;
    

    对于像您的矩阵这样的多维数组,NArray 使用带有乘数偏移的单个指针,类似于您的matA[i * colsA + j] - 详细介绍这将太长,但希望这足以帮助您决定这是否适合您。

    我实际上在一些个人项目中经常使用这种方法。它们是 MIT 许可的,因此请随意浏览它们并复制或重用任何内容。这个neural network layer class 可能包含一些有用的参考代码。

    【讨论】:

    • 感谢您提供更多信息。我现在会坚持我的方法,因为我还有其他优先事项,但我肯定会在不久的将来回顾你提出的替代方案。
    猜你喜欢
    • 1970-01-01
    • 2012-01-12
    • 2014-08-22
    • 1970-01-01
    • 2019-09-29
    • 1970-01-01
    • 1970-01-01
    • 2015-07-02
    • 2016-04-01
    相关资源
    最近更新 更多