Принятие неопределенного числа аргументов в Ruby / Inline C - PullRequest
3 голосов
/ 31 января 2012

Я пытаюсь переписать высокорекурсивную функцию, используя встроенный 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 ]

1 голос
/ 31 января 2012

Вместо использования builder.c, попробуйте builder.c_raw (или builder.c_raw_singleton) при определении ваших методов. Возможно, вы захотите добавить VALUE self в конец списка аргументов, но, похоже, он работает с моими тестами или без них. Возможно, также стоит явно указать арность, просто чтобы быть в безопасности:

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.

0 голосов
/ 31 января 2012

Если я не ошибаюсь, вы хотите это:

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 со всеми аргументами.

...