From: "Mauricio Fernández" Date: 2003-11-22T23:55:13+09:00 Subject: Re: Invoking method with a block in C extension --nFreZHaLTZJo0R7j Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Sat, Nov 22, 2003 at 10:34:27PM +0900, Dmitry V. Sabanin wrote: > Hi. > I'm converting some of my ruby code to C extension for better perfomance. > I ran into problems with executing methods that take blocks. > I.e. in ruby i have > string.gsub!(/regexp/) { |subst| ... } > and i can't find the way to translate it to C. I tried to search through > ruby-talk archives, but I couldn't find anything usefull. > As far as I was looking at problem, I found rb_iterate, rb_yield, but I > couldn't clearly understand what's their purpose, and how to get them all > together to achieve what I want. > Could somebody please explain me how can I implement this ruby code in C? > I'd really appreciate any help. Thanks in advance! I was surprised to see that rb_funcall propagates the block passed with rb_iterate, so there's 2 solutions (attached). -- _ _ | |__ __ _| |_ ___ _ __ ___ __ _ _ __ | '_ \ / _` | __/ __| '_ ` _ \ / _` | '_ \ | |_) | (_| | |_\__ \ | | | | | (_| | | | | |_.__/ \__,_|\__|___/_| |_| |_|\__,_|_| |_| Running Debian GNU/Linux Sid (unstable) batsman dot geo at yahoo dot com Linux! Guerrilla UNIX Development Venimus, Vidimus, Dolavimus. -- Mark A. Horton KA4YBR, mah@ka4ybr.com --nFreZHaLTZJo0R7j Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="extconf.rb" require "mkmf" create_makefile("gsub_example") --nFreZHaLTZJo0R7j Content-Type: text/x-csrc; charset=us-ascii Content-Disposition: attachment; filename="gsub_example.c" #include #include VALUE mCTest; static VALUE block(VALUE args) { VALUE str = rb_ary_entry(args, 0); Check_Type(str, T_STRING); printf("Inside block, with string: %s.\n", RSTRING(str)->ptr); return rb_funcall(str, rb_intern("upcase"), 0); } static VALUE block2(VALUE str) { Check_Type(str, T_STRING); printf("Inside block, with string: %s.\n", RSTRING(str)->ptr); return rb_funcall(str, rb_intern("upcase"), 0); } static VALUE foo(VALUE self, VALUE str, VALUE re) { VALUE proc; proc = rb_proc_new(block, Qnil); return rb_funcall(str, rb_intern("_gsub!"), 2, re, proc); } static VALUE call_gsub(VALUE args) { VALUE str, re; str = rb_ary_entry(args, 0); re = rb_ary_entry(args, 1); return rb_funcall(str, rb_intern("gsub!"), 1, re); } static VALUE foo2(VALUE self, VALUE str, VALUE re) { VALUE args; args = rb_ary_new(); rb_ary_push(args, str); rb_ary_push(args, re); return rb_iterate(call_gsub, args, block2, str); } void Init_gsub_example() { mCTest = rb_define_module("CTest"); rb_define_singleton_method(mCTest, "foo", foo, 2); rb_define_singleton_method(mCTest, "foo2", foo2, 2); rb_eval_string("class String; def _gsub!(re,block); gsub!(re,&block) end end"); } --nFreZHaLTZJo0R7j Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="tst.rb" require "gsub_example" a = "hello, world!" CTest.foo(a, /[ehl]/) p a b = "hello, world!" CTest.foo2(b, /[ehl]/) p b --nFreZHaLTZJo0R7j--