Ruby C扩展:将int函数转换为ruby值

时间:2015-11-04 05:33:46

标签: c ruby

我试图将以下函数包装成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部分,但这些部分专注于对象创建/分配。我试图提供一个执行某些转换并返回值的函数,因此我无法在概念上进行匹配。

1 个答案:

答案 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);
    }