Re: rb_yield(), break, and C extensions
- From: "Kent Sibilev" <ksruby@xxxxxxxxx>
- Date: Sun, 8 Apr 2007 04:39:09 +0900
On 4/7/07, Kent Sibilev <ksruby@xxxxxxxxx> wrote:
On 4/7/07, Noah Easterly <noah.easterly@xxxxxxxxx> wrote:
> On Apr 7, 1:08 pm, "Kent Sibilev" <ksr...@xxxxxxxxx> wrote:
> > You should wrap your rb_yield call with rb_ensure. From README.EXT:
> >
> > VALUE rb_ensure(VALUE (*func1)(), void *arg1, void (*func2)(), void *arg2)
> >
> > Calls the function func1 with arg1 as the argument, then calls func2
> > with arg2 if execution terminated. The return value from
> > rb_ensure() is that of func1.
>
> Hmm.... this doesn't seem to have the desired effect. I'm pretty sure
> rb_ensure() is just for handling exceptions, not breaks.
>
> According to ruby.h and the Pickaxe, the function def'n has changed a
> bit too. From Programming Ruby(2nd ed):
>
> VALUE rb_ensure(VALUE(*body)(), VALUE args, VALUE(*ensure)(), VALUE
> eargs)
>
> Executes body with the given args. Whether or not an exception is
> raised, execute ensure with the given eargs after body has completed.
>
> So it seems that rb_ensure is just for exceptions, not 'break'. I
> tried tweaking my code to use it anyway, but the ensure call is still
> bypassed when there is a break. For example:
>
> >>> lib.c
> void func( int n, int (*callback)(void) )
> {
> printf("before callback...\n");
> if (callback() < 0)
> goto cleanup;
> printf("after callback...\n");
> cleanup:
> printf("in cleanup...\n");
> }
> >>> ext.c
> static void
> my_ensure(void * ptr)
> {
> *(int *)ptr = -1;
> }
> static int
> meth_callback(void)
> {
> int retval = 0;
> rb_ensure(rb_yield, Qnil, my_ensure, &retval);
> return retval;
> }
> // ...
> >>> test.rb
>
> require 'ext'
> YYY.new.meth(100) { } # outputs "before callback...\n", "in cleanup...
> \n"
> YYY.new.meth(100) { break } # outputs "before callback...\n"
>
What I meant was that your cleanup code should be in my_ensure
function and not in func itself. Just to prove my point:
$ cat t.rb
def test
puts 'pre'
yield
puts 'post'
ensure
puts 'ensure'
end
test {break}
$ ruby t.rb
pre
ensure
OK, maybe this code will clean things up:
$ cat t.rb
require 'rubygems'
require 'inline'
class MyTest
inline do |builder|
builder.prefix <<-EOC
static VALUE
func(VALUE arg)
{
printf("pre\\n");
rb_yield(arg);
printf("post\\n");
return Qnil;
}
static VALUE
cleanup(VALUE arg)
{
printf("ensure\\n");
return Qnil;
}
EOC
builder.c <<-EOC
void my_func()
{
rb_ensure(func, Qnil, cleanup, Qnil);
}
EOC
end
end
MyTest.new.my_func {break}
$ ruby t.rb
pre
ensure
$
--
Kent
---
http://www.datanoise.com
.
- Follow-Ups:
- Re: rb_yield(), break, and C extensions
- From: Noah Easterly
- Re: rb_yield(), break, and C extensions
- References:
- rb_yield(), break, and C extensions
- From: Noah Easterly
- Re: rb_yield(), break, and C extensions
- From: Kent Sibilev
- Re: rb_yield(), break, and C extensions
- From: Noah Easterly
- Re: rb_yield(), break, and C extensions
- From: Kent Sibilev
- rb_yield(), break, and C extensions
- Prev by Date: Re: Method constant arguments
- Next by Date: Re: rb_yield(), break, and C extensions
- Previous by thread: Re: rb_yield(), break, and C extensions
- Next by thread: Re: rb_yield(), break, and C extensions
- Index(es):
Relevant Pages
|