Ruby(2.0)c扩展从c函数返回数组的数组

Ruby(2.0)c扩展从c函数返回数组的数组,c,ruby,ruby-c-extension,C,Ruby,Ruby C Extension,我正在编写一个Ruby c扩展来使用Acceleratemacos框架执行线性代数计算。为了使用所有可用的内核,我还使用了rb\u thread\u call\u without\u gvl来解锁全局VM锁 我不是c专家,所以请容忍我 其想法是创建一个对两个输入矩阵进行操作的ruby方法 VALUE matmat_mul(VALUE self, VALUE matrixA, VALUE matrixB) 在这个方法中,我创建了一个struct,然后将其传递给实际函数 void* matmat_

我正在编写一个Ruby c扩展来使用
Accelerate
macos
框架执行线性代数计算。为了使用所有可用的内核,我还使用了
rb\u thread\u call\u without\u gvl
来解锁全局VM锁

我不是c专家,所以请容忍我

其想法是创建一个对两个输入矩阵进行操作的ruby方法

VALUE matmat_mul(VALUE self, VALUE matrixA, VALUE matrixB)
在这个方法中,我创建了一个
struct
,然后将其传递给实际函数

void* matmat_mul_nogvl(void* inputMatricesPtr)
您可以从输出中看到,在c代码中,一切都按照预期工作,但我很难理解如何从c代码返回最终矩阵(数组数组)。最后一个矩阵是
nil
。我想我错过了将
matC
转换回Ruby对象的部分

这是到目前为止我的代码(有很多调试
printf
来验证计算是否正确)

并使用以下ruby代码对其进行测试

require './blasnogvl'

puts "#{Time.now} - Started"

rows = 4
cols = 3
mat = Array.new(rows){Array.new(cols){rand}}
puts "#{Time.now} - Matrix generated"
mat[0] = [0.0, 1.0, 2.0]
mat[1] = [3.0, 4.0, 5.0]
mat[2] = [6.0, 7.0, 8.0]
mat[3] = [6.0, 7.0, 8.0]
puts mat.to_s

matA = mat
matB = mat.transpose
operation = RG::LinearAlgebra::Operation.new
matC = operation.matmat_mul(matA, matB)

puts "After calculation matA is"
puts matA.to_s

puts "After calculation matB is"
puts matB.to_s

puts "matC in ruby is"
puts matC.to_s
puts "#{Time.now} - Matrix calculated"

您的
matmat_mul
函数调用的最终值
return Qnil
,这基本上是ruby中的
return nil

因此,您需要为矩阵创建ruby数组,创建一个数组来保存每行数据,填充这些行并将它们推入结果数组


首先可以通过
rb_ary_new
实现,但是由于尺寸已经知道,我们可以给ruby一个提示,它将使用
rb_ary_new_capa
,大小是多少,然后用
rb_ary_push
填充值,这是
matmatmat_mul
函数调用的
return Qnil
Array

最终值的实现,这在ruby中基本上是
return nil

因此,您需要为矩阵创建ruby数组,创建一个数组来保存每行数据,填充这些行并将它们推入结果数组

首先可以通过
rb\u ary\u new
来实现,但是由于维度已经知道,我们可以给ruby一个提示,它将使用
rb\u ary\u new\u capa
,然后用
rb\u ary\u push
填充值,这是
数组的一个实现#
require 'mkmf'
extension_name = 'blasnogvl'
have_framework('Accelerate')
create_makefile(extension_name)
require './blasnogvl'

puts "#{Time.now} - Started"

rows = 4
cols = 3
mat = Array.new(rows){Array.new(cols){rand}}
puts "#{Time.now} - Matrix generated"
mat[0] = [0.0, 1.0, 2.0]
mat[1] = [3.0, 4.0, 5.0]
mat[2] = [6.0, 7.0, 8.0]
mat[3] = [6.0, 7.0, 8.0]
puts mat.to_s

matA = mat
matB = mat.transpose
operation = RG::LinearAlgebra::Operation.new
matC = operation.matmat_mul(matA, matB)

puts "After calculation matA is"
puts matA.to_s

puts "After calculation matB is"
puts matB.to_s

puts "matC in ruby is"
puts matC.to_s
puts "#{Time.now} - Matrix calculated"
// Multiplication code above ...
VALUE matrixC = rb_ary_new_capa(rowsC);

for (i = 0; i < rowsC; i++) {
    VALUE rowC = rb_ary_new_capa(colsC);

    for (j = 0; j < colsC; j++)
        rb_ary_push(rowC, DBL2NUM(matC[i * colsC + j]);

    rb_ary_push(matrixC, rowC);
}

return matrixC;