From: Noah Easterly Date: 2007-04-08T01:30:09+09:00 Subject: rb_yield(), break, and C extensions So, I'm working on a C extension. One of my C functions uses a callback function, so when I wrap that function in a method, I pass it a callback function that just wraps a call to rb_yield(). This works great, except that when the block passed to the method includes a 'break' statement, the end of the C function is bypassed, and so it can't do its own cleanup. What I'd like to do is "catch" the break somehow, so I can tell my C function to exit and cleanup before restoring control to the ruby script. Is there any way to do this? I realize it could be a Bad Thing if abused, but this is for good, I swear. I guess I could try to pull all the memory allocation/file opening/etc out to the containing object, but [1] I'm not sure it's possible. [2] It seems kind of awkward. [3] This wouldn't solve the problem if I was linking in to an existing object file that I didn't have source for. Here's some toy code, if I didn't get my point across: >>> lib.c void func( int n, int (*callback)(void) ) { void * mem = malloc(sizeof(int)); FILE * file = fopen("filename", "r"); int i; // ... do stuff for (i = 0; i < n; i++) { if (callback() < 0) { goto cleanup; } } // ... do more stuff cleanup: if (mem) { free(mem); } if (file) { fclose(file); } } >>> ext.c static int meth_callback(void) { rb_yield(Qnil); return 0; } static VALUE yyy_meth(VALUE self, VALUE count) { func(FIX2INT(count), meth_callback); return Qnil; } >>> test.rb require 'ext' YYY.new.meth(100) { break }