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: basile<at>starynkevitch<dot>net 
aliases: basile<at>tunes<dot>org = bstarynk<at>nerim<dot>net
8, rue de la FaýÆncerie, 92340 Bourg La Reine, France