私はかなり基本的な反復であるべきものを扱っています。Rubyコードでそれを達成できることは理解していますが、すでにC拡張で作業しているので、この関数を残りのコードと一緒にCで保持することをお勧めします。問題。
問題は rb_block_call にあります。README.EXT での rb_block_call の説明は次のとおりです。
VALUE rb_block_call(VALUE recv, ID mid, int argc, VALUE * argv, VALUE (*func) (ANYARGS), VALUE data2)
シンボル mid で指定されたメソッド名で recv のメソッドを呼び出し、ブロックとして func を提供します。func は、yield からの値を最初の引数として、data2 を 2 番目の引数として、argc/argv を 3 番目または 4 番目の引数として受け取ります。
したがって、私の理解では (Ruby の内部を調べて確認しました)、受信関数は次のようになります。
VALUE function( VALUE rb_yield_value, VALUE data2, int argc, VALUE argv );
そして、ここで問題にぶつかりました。私の使用例 (以下に含めます) では、rb_yield_value と data2 が期待どおりに渡されます。一方、argc は常に 1 に設定され、argv[ 0 ] は rb_yield_value、argv[ 1 ] は false、argv[ 2 ] は rb_yield_value、argv[ 3 ] は例外をスローします。
argc と argv に何を渡すかは問題ではありません。0 と NULL を渡すと、1 と VALUE を Qtrue に設定した場合と同じ結果になります。argc/argv を使用するものはすべて説明どおりです。
ここに私が取り組んでいるコードがあります:
VALUE rb_RPBDB_DatabaseObject_internal_cursorForCallingContext( VALUE rb_self ) {
// when we are looking for the contextual iterator, we look up the current backtrace
// at each level of the backtrace we have an object and a method;
// if this object and method match keys present in self (tracking calling contexts for iteration in this iteration class) return cursor
VALUE rb_cursor_context_storage_hash = rb_RPBDB_DatabaseObject_internal_cursorContextStorageHash( rb_self );
VALUE rb_cursor = Qnil;
if ( RHASH_SIZE( rb_cursor_context_storage_hash ) ) {
rb_block_call( rb_mKernel,
rb_intern( "each_backtrace_frame" ),
1,
& rb_cursor_context_storage_hash,
rb_RPBDB_DatabaseObject_internal_each_backtrace_frame,
rb_cursor );
}
return rb_cursor;
}
// walk up the stack one frame at a time
// for each frame we need to see if object/method are defined in our context storage hash
VALUE rb_RPBDB_DatabaseObject_internal_each_backtrace_frame( VALUE rb_this_backtrace_frame_hash,
VALUE rb_cursor_return,
int argc,
VALUE* args ) {
// why are we getting 3 args when argc is 1 and none of the 3 match what was passed?
VALUE rb_cursor_context_storage_hash = args[ 0 ];
// each frame is identifiable as object/method
VALUE rb_this_frame_object = rb_hash_aref( rb_this_backtrace_frame_hash,
ID2SYM( rb_intern( "object" ) ) );
VALUE rb_this_frame_method = rb_hash_aref( rb_this_backtrace_frame_hash,
ID2SYM( rb_intern( "method" ) ) );
// we likely have "block in ..." for our method; we only want the "..."
rb_this_frame_method = ID2SYM( rb_to_id( rb_funcall( rb_obj_as_string( rb_this_frame_method ),
rb_intern( "gsub" ),
2,
rb_str_new2( "block in " ),
rb_str_new2( "" ) ) ) );
VALUE rb_cursor_object_context_hash = rb_RPBDB_DatabaseObject_internal_cursorObjectContextStorageHash( rb_cursor_context_storage_hash,
rb_this_frame_object);
if ( RHASH_SIZE( rb_cursor_object_context_hash ) ) {
rb_cursor_return = rb_hash_aref( rb_cursor_object_context_hash,
rb_this_frame_method );
}
return rb_cursor_return;
}
Ruby の内部では、argc/argv を使用した rb_block_call の例はあまりないようです...せいぜい 1 つまたは 2 つです。それらはすべて、値を使用するのではなく、単に値を内部で中継していると思います。
考え?