Начиная с этого:
./backtrack_inline.rb:73: error: too few arguments to function 'backtrack'
Если вы посмотрите на сгенерированный код, функция backtrack
определена в строке 29:
static VALUE backtrack(VALUE self, VALUE _ss, VALUE _s, VALUE _p, VALUE _mm, VALUE _ins, VALUE _del) { ... }
У него есть семь аргументов, исходные шесть, плюс VALUE self
, поскольку он был преобразован в метод класса Scan
.
Вызов этой функции в строке 67 выглядит следующим образом:
end = backtrack(ss, s, p, mm, ins, del);
У него только шесть аргументов. RubyInline не преобразует это в вызов метода объекта, а просто копирует его дословно. Отсюда и предупреждения о makes integer from pointer without a cast
: определение функции было преобразовано в VALUE
с, но вы вызываете с исходными типами.
Сообщение об ошибке говорит, что ошибка от строки 73 в backtrack_inline.rb
из-за директивы в строке 54 сгенерированного кода:
# line 61 "./backtrack_inline.rb"
, который в основном говорит компилятору "сбрасывать" свои строки и значения файла для ошибок и обрабатывать следующую строку (55) как строку 61 в файле ./backtrack_inline.rb
. Фактическая строка - 67, 12 перед 55, но компилятор сообщает, что это 73, 12 перед 61 (значение, в которое он был сброшен) и из другого файла. Этот метод не работает в этом случае, так как он не учитывает дополнительные строки, добавленные RubyInline. Фактическая строка в источнике - 69.
Простым исправлением для этого является изменение определения функции backtrack
, чтобы она была просто функцией C, а не добавление ее в качестве метода для объекта. Измените builder.c
на builder.prefix
(в строке 38 вашего файла Ruby). Это не сработает, если вы хотите, чтобы backtrack
был доступен в качестве метода для объекта в Ruby. Если это так, то вам может потребоваться создать другую функцию, которая будет методом, который затем обернет «реальную» функцию возврата.
Далее, глядя на
./backtrack_inline.rb:67: error: lvalue required as unary '&' operand
На самом деле это относится к строке 61 сгенерированного кода, которая выглядит следующим образом:
char* s = StringValuePtr(rb_iv_get(self, "@seq"));
StringValuePtr
- это макрос , который определяется как :
#define StringValue(v) rb_string_value(&(v))
Отсюда и &
в lvalue required as unary '&' operand
. Вам нужно добавить локальную переменную, которая будет lvalue:
VALUE seq = rb_iv_get(self, "@seq");
char* s = StringValuePtr(seq);
В моем случае (Mac OS X Snow Leopard, Ruby 1.9.3-p0, RubyInline 3.11.0) эти два изменения сделали скрипт запущенным без ошибок, но выдало предупреждение:
backtrack_inline.rb:47: warning: implicit conversion shortens 64-bit value into a 32-bit value
На самом деле это относится к строке 46 файла ruby:
return (s - ss) - 1;
s
и ss
равны char *
, т. Е. 64-битные указатели (на этом аппарате), а тип возвращаемого значения функции - int
- 32 бита. Добавление явного приведения исправило это:
return (int)((s - ss) - 1);
Теперь он работает без ошибок:
ruby-inline $ ruby backtrack_inline.rb
14
ruby-inline $
(Надеюсь, 14 правильный ответ!)
Вот версия скрипта с этими изменениями .