Ruby C API - 从ruby数组到C数组
Ruby C API - From ruby array to C array
我正在将数组(矩阵)从 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
}
是否有 better/quicker 方法将 Ruby 数组转换为 C 数组,反之亦然?
不,没有更快的方法将 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 可能包含一些有用的参考代码。
我正在将数组(矩阵)从 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
}
是否有 better/quicker 方法将 Ruby 数组转换为 C 数组,反之亦然?
不,没有更快的方法将 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 可能包含一些有用的参考代码。