接受Ruby / Inline C中未定义数量的参数

时间:2012-01-31 01:23:17

标签: c ruby variadic-functions splat ruby-c-extension

我正在尝试使用内联C和Ruby重写一个高度递归的函数。该函数接受一个未定义数量的参数,即它在Ruby中看起来像这样:

    def each_entity(*types)
      # Do something and recurse.
    end

我正在尝试使用以下代码在内联C中模仿它:

    VALUE each_entity_c(int argc, VALUE *argv)
    {
      // ...
    }

但这会产生编译错误:

inline.rb:486:in `ruby2c': Unknown type "VALUE *" (ArgumentError)

这是在C中完成此操作的正确方法吗?如果是这样,可能导致此错误的原因是什么?如果没有,它是如何完成的?

2 个答案:

答案 0 :(得分:1)

在定义方法时,请尝试builder.c(或builder.c_raw),而不是使用builder.c_raw_singleton。您可能希望将VALUE self添加到a​​rgs列表的末尾,但它似乎可以在我的测试中使用或不使用。为了安全起见,也可能值得明确指定arity:

inline do |builder|

  builder.c_raw <<-EOS, :arity => -1
    VALUE each_entity_c(int argc, VALUE *argv, VALUE self)
    {
      // ...
    }
  EOS
end

使用builder.c,Ruby Inline将重写该函数,使其接受Ruby VALUE类型作为参数,并添加代码以将这些类型转换为原始类型中的c类型。您正在编写已经需要VALUE个参数的代码,因此不希望完成此转换,因此您需要使用c_raw

答案 1 :(得分:0)

如果我没弄错的话,你想要这个:

VALUE each_entity_c(VALUE self, VALUE args)
{
    // args is a Ruby array with all arguments
}
rb_define_method(class, "MyClass", each_entity_c, -2);

给C函数一个带有所有参数的Ruby数组。