From: ts Date: 2001-09-26T15:26:23+09:00 Subject: [ruby-talk:21709] Re: Extension Question: Block Parameters >>>>> "J" == Jason Voegele writes: J> If a block is provided, the foo method should pass along the block to J> the bar method. I couldn't find any documentation on this. You can use the parameter "&" to rb_scan_args(), for example : VALUE block; rb_scan_args(argc, argv, "0&", &block); in this case ruby will just do : block = Qnil; if (rb_block_given_p()) { block = rb_f_lambda(); } perhaps faster to write it rather than call rb_scan_args() :-)) A more generic way to write it, is something like this (it's important to call rb_iterate() to propagate the block) pigeon% cat tt.c #include static VALUE tt_bar(argc, argv, obj) int argc; VALUE obj, *argv; { if (rb_block_given_p()) { VALUE tt = INT2FIX(12); if (argc) { tt = argv[0]; } rb_yield(tt); } return obj; } static VALUE tt_iter(tmp) VALUE *tmp; { return rb_funcall2(tmp[2], rb_intern("bar"), (int)tmp[0], (VALUE *)tmp[1]); } static VALUE tt_yield(obj, res) VALUE obj, res; { rb_ary_push(res, rb_yield(obj)); return Qnil; } static VALUE tt_foo(argc, argv, obj) int argc; VALUE obj, *argv; { if (rb_block_given_p()) { VALUE res, tmp[3]; tmp[0] = (VALUE)argc; tmp[1] = (VALUE)argv; tmp[2] = obj; res = rb_ary_new(); rb_iterate(tt_iter, (VALUE)tmp, tt_yield, res); return res; } return Qnil; } void Init_tt() { VALUE tt_cTt = rb_define_class("Tt", rb_cObject); rb_define_method(tt_cTt, "foo", tt_foo, -1); rb_define_method(tt_cTt, "bar", tt_bar, -1); } pigeon% pigeon% cat b.rb #!/usr/bin/ruby require 'tt' a = Tt.new.foo { |i| puts i; i * 12 } p a pigeon% pigeon% b.rb 12 [144] pigeon% Guy Decoux