A summary for people embedding Ruby
To answer to my previous questions (thanks to hint by Guy Decoux) here
is the way to register a callback (ie how to call a ruby routine from
C)
declare a static value (to contain the called proc)
/*in C */
static VALUE hook_block;
don’t forget to register in to the GC with
/* in C, inside your initialisation */
rb_global_variable (&hook_block);
to be able to register the hook using
in ruby
register_hook do |arg1|
#do something with arg1
end
the C code for register_hook should be like
/C code for register_hook/
static VALUE my_register_hook(VALUE self) {
if (rb_block_given_p ()) {
/* a block was given - remember it /
hook_block = rb_block_proc ();
} else {
/ no block given, clear the hook */
hook_block = Qfalse;
}
}
and the initialisation should contain
/* in C, inside your initialisation */
rb_define_module_function (your_module, “register_hook”,
my_register_hook, 0);
to call the hook from a C function you first test that the hook is a
procedure
/* in C, checking the hook */
if (!rb_obj_is_kind_of (hook_block, rb_cProc))
return;
you might also need to protect the hook call against ruby exceptions
or error, eg with
/* in C calling the hook */
VALUE arghook = somethinguseful;
VALUE argres = somethinguseful;
rb_rescue (hook_handler, arghook, hook_rescuer, argres);
where the hook_handler is something like
/* in C hook handler */
static VALUE hook_handler(VALUE arghook) {
VALUE res = 0;
VALUE tabarg[1] = { 0 };
int call_id = rb_intern (“call”);
tabarg[0] = arghook;
res = rb_funcall2 (hook_block, call_id, 1, tabarg);
return res;
}
and the hook_rescuer compute result when an exception happened, eg
/* in C /
static VALUE hook_rescuer (VALUE argres) {
/ etc */
}
Even with serious help I spent more than an hour finding this out. I
suggest it should be documented somewhere!
I use this in Guis (an opensource GTK widget server) see
http://www.starynkevitch.net/Basile/guisdoc.html
···
–
Basile STARYNKEVITCH http://starynkevitch.net/Basile/
email: basilestarynkevitchnet
aliases: basiletunesorg = bstarynknerimnet
8, rue de la Faïencerie, 92340 Bourg La Reine, France