【问题标题】:Ruby C extension: turning int function into ruby valueRuby C 扩展:将 int 函数转换为 ruby​​ 值
【发布时间】:2015-11-04 05:33:45
【问题描述】:

我正在尝试包装以下函数以进行 C 扩展。

int dsvd(float **a, int m, int n, float *w, float **v){
    //do some things
}

我有我的 init,但不太正确:

void Init_svd() {
    VALUE rb_mSvd = rb_define_module("Svd");
    rb_define_method(rb_mSvd, "svd", dsvd, 0);
}

我知道我需要包装 dsvd 以便我可以将 Value 传递给 rb_define_method,但我无法确定正确的方法。我尝试调整this 答案,但无法完全弄清楚。有什么建议吗?

edit* 我还阅读了关于 C 扩展的实用程序员部分,但它侧重于对象创建/分配。我正在尝试提供一个执行一些转换并返回一个值的函数,所以我无法在概念上进行匹配。

【问题讨论】:

    标签: c ruby


    【解决方案1】:

    如果整数适合 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);
        }
    

    【讨论】:

    • 那么我会做类似VALUE rb_svd(VALUE self, VALUE **a, VALUE m, VALUE n, VALUE *w, VALUE **v){} 之类的事情还是应该解开参数?
    • 太棒了!谢谢,这似乎可以解决问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-13
    • 2012-02-12
    • 2017-03-16
    • 2023-03-13
    • 2013-02-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多