我试图将以下函数包装成C扩展名。
int dsvd(float **a, int m, int n, float *w, float **v){
//do some things
}
我有我的初学者,这不是很正确:
void Init_svd() {
VALUE rb_mSvd = rb_define_module("Svd");
rb_define_method(rb_mSvd, "svd", dsvd, 0);
}
我知道我需要包装dsvd以便我可以将Value
传递给rb_define_method
,但我无法找到正确的方法。我尝试调整this回答,但无法弄明白。有什么建议吗?
编辑*我还阅读了有关C扩展的Pragmatic Programmer部分,但这些部分专注于对象创建/分配。我试图提供一个执行某些转换并返回值的函数,因此我无法在概念上进行匹配。
答案 0 :(得分:2)
如果整数适合Fixnum,则可以使用宏INT2FIX返回dsvd()返回的整数的Fixnum值。否则你必须使用INT2NUM,它具有函数调用开销(它调用rb_int2inum)。在ruby.h中查找这些宏以获取更多详细信息。
已编辑:您的评论表明您需要批次更多帮助。你想要这样的东西。我没有编译这个,它没有检查参数的健全性,但它应该让你去)。您的方法的签名看起来像数组a和v中传递的值可能会更改,并且此代码不会复制对Ruby版本的任何更改(使用rb_ary_store来分配元素)。
#include <ruby.h>
#include <ruby/intern.h>
static VALUE rb_mSvd;
static VALUE
rb_svd(VALUE self, VALUE a_array, VALUE m_v, VALUE n_v, VALUE w_v, VALUE v_array)
{
/* Note that there is no checking here for correct types or sane values! */
long a_len = RARRAY_LEN(a_array); /* get the length of first (array) argument */
float* a = (float*)malloc(sizeof(float)*a_len); /* make space for the copies */
int m = NUM2INT(m_v);
int n = NUM2INT(n_v);
float w = NUM2DBL(w_v);
long v_len = RARRAY_LEN(v_array);
float* v = (float*)malloc(sizeof(float)*v_len);
int result;
for (int i = 0; i < a_len; i++)
a[i] = NUM2DBL(rb_ary_entry(a_array, i));
for (int i = 0; i < v_len; i++)
v[i] = NUM2DBL(rb_ary_entry(v_array, i));
result = dsvd(&a, m, n, w, &v);
free(a);
free(v);
return INT2NUM(result);
}
void Init_svd()
{
rb_mSvd = rb_define_module("Svd");
rb_define_method(rb_mSvd, "svd", rb_svd, 5);
}