これから始めます:
./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) { ... }
これには、元の 6 つに加えて、クラスVALUE self
のメソッドに変換されているため、7 つの引数があります。Scan
67 行目のこの関数の呼び出しは次のようになります。
end = backtrack(ss, s, p, mm, ins, del);
引数は 6 つしかありません。RubyInline はこれをオブジェクトのメソッド呼び出しに変換せず、そのままコピーするだけです。これは、警告が発生する場所でもありますmakes integer from pointer without a cast
。関数定義は take に変換されてVALUE
いますが、元の型で呼び出しています。
エラー メッセージはbacktrack_inline.rb
、生成されたコードの 54 行目のディレクティブが原因で、エラーが 73 行目から発生したことを示しています。
# line 61 "./backtrack_inline.rb"
これは基本的に、エラーの行とファイルの値を「リセット」し、次の行 (55) をファイルの行 61 として扱うようにコンパイラに指示します./backtrack_inline.rb
。実際の行は 67、55 より 12 進んでいますが、コンパイラは 73、61 (リセットされた値) より 12 進んでおり、異なるファイルからのものであると報告します。この手法は、RubyInline によって追加される余分な行を考慮していないため、この場合には実際には機能しません。ソースの実際の行は 69 です。
これを簡単に修正するには、関数の定義をbacktrack
オブジェクトのメソッドとして追加するのではなく、単なる C 関数に変更します。(Ruby ファイルの 38 行目) に変更builder.c
します。Ruby でオブジェクトのメソッドとして使用可能にしbuilder.prefix
たい場合、これは機能しません。backtrack
その場合は、別の関数をメソッドとして作成する必要がある場合があります。これにより、「実際の」バックトラック関数がラップされます。
次に見ると、
./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
由来です。左辺値になるローカル変数を追加する必要があります。
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)、これら 2 つの変更により、スクリプトはエラーなしで実行されましたが、警告が表示されました。
backtrack_inline.rb:47: warning: implicit conversion shortens 64-bit value into a 32-bit value
これは、実際には ruby ファイルの 46 行目を指します。
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が正解だといいのですが!)
これらの変更を加えたバージョンのスクリプトを次に示します。