Accepting an undefined number of arguments in Ruby/Inline C

444 views Asked by At

I am trying to rewrite a highly recursive function using inline C with Ruby. The function accepts an undefined number of arguments, i.e. it would look like this in Ruby:

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

I am trying to mimick this in inline C using the following code:

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

But this yields the compile error:

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

Is this the correct way to accomplish this in C? If so, what could have caused this error? If not, how is it done?

2

There are 2 answers

0
matt On BEST ANSWER

Instead of using builder.c, try builder.c_raw (or builder.c_raw_singleton) when defining your methods. You might want to add VALUE self to the end of the args list, but it seems to work with or without in my tests. It might also be worth explicitly specifying the arity, just to be safe:

inline do |builder|

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

Using builder.c, Ruby Inline will rewrite the function so that it accepts Ruby VALUE types as parameters, and add code to convert these to the c types in your original. You're writing code that already expects VALUE arguments so don't want this conversion to be done, so you need to use c_raw.

0
molf On

If I'm not mistaken, you want to you this:

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);

The C function is given a Ruby array with all arguments.