6

この Ruby インライン C コードhttp://pastie.org/2825882を機能させようとしています。コードはバニラ C で動作しますが、ここではエラーと警告が表示されます。このエラーの原因は何ですか?

./backtrack_inline.rb:67: error: lvalue required as unary '&' operand

また、次のエラーが表示されるのはなぜですか?

./backtrack_inline.rb:73: error: too few arguments to function 'backtrack'

結果の C コード ( http://pastie.org/2826036 ) を調べると、引数に問題はありません。ただし、次の警告も表示されます。

./backtrack_inline.rb:73: warning: passing argument 1 of 'backtrack' makes integer from pointer without a cast
./backtrack_inline.rb:73: warning: passing argument 2 of 'backtrack' makes integer from pointer without a cast
./backtrack_inline.rb:73: warning: passing argument 3 of 'backtrack' makes integer from pointer without a cast
4

3 に答える 3

5

これから始めます:

./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;

ssschar *、つまり 64 ビット ポインター (このマシン上) であり、関数の戻り値の型はint- 32 ビットです。明示的なキャストを追加すると、これが修正されました。

return (int)((s - ss) - 1);

きれいに動作するようになりました:

ruby-inline $ ruby backtrack_inline.rb 
14
ruby-inline $ 

(14が正解だといいのですが!)

これらの変更を加えたバージョンのスクリプトを次に示します

于 2011-11-09T22:47:50.003 に答える
1

OK、この質問は Ruby フォーラムでも回答されています。

http://www.ruby-forum.com/topic/2959614

于 2011-11-16T20:10:55.817 に答える
0

わかりました...これについてもう少し考えました。

変数 end を呼び出しています。これは C の予約語ではありませんが、Ruby はこれを参照するべきではありませんが、Ruby が混乱している可能性があります。

念のため、名前を変更することをお勧めします。それを除外するだけでも価値があります。

于 2011-11-09T18:15:38.840 に答える