Invoking method with a block in C extension

D

Dmitry V. Sabanin

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!
 
T

ts

D> As far as I was looking at problem, I found rb_iterate, rb_yield, but I
D> couldn't clearly understand what's their purpose, and how to get them all
D> together to achieve what I want.

Look in enum.c in the distribution of ruby, you have examples for call to
rb_iterate



Guy Decoux
 
M

Mauricio Fernández

--nFreZHaLTZJo0R7j
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

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, (e-mail address removed)

--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 <ruby.h>
#include <stdio.h>

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--
 
D

Dmitry V. Sabanin

I was surprised to see that rb_funcall propagates the block passed with
rb_iterate, so there's 2 solutions (attached).
Thank you very much, that code saved me :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,141
Messages
2,570,813
Members
47,357
Latest member
sitele8746

Latest Threads

Top