From: Bryan Murphy Date: 2001-06-27T04:56:38+09:00 Subject: [ruby-talk:16931] Embedded Ruby Request Hey guys! I'm embedding Ruby in my most recent application, and using it as a glue to to piece all my C/C++ modules together. I've found the default implementation of rb_protect() usefull, but somewhat lacking. I frequently call handlers written in ruby from my C/C++ code using the rb_funcall functions. Of course, the problem with that is that when there is a problem with the ruby script, my application exits out rather ungracefully, hence the need for rb_protect. My application will potentially have MANY MANY callbacks implemented in it by the time it is done, and it is very inconvenient to write C wrapper functions for each callback and pass those wrapper functions to rb_protect. Because of this, I've modified eval.c and ruby.h to add a couple extra functions. These funtions work like a combination of rb_protect combined with rb_load_file, rb_require, rb_funcall2, or rb_funcall3 (I did not implement a version of rb_funcall since I did not want to create a duplicate of the functionality in that function). I've found these functions very usefull, and they will save me a lot of uneccessary coding effort. I feel they are worth including in the next version of Ruby, so I'm submitting them here with the hopes that they will be included and hopefully help somebody else out in the future. Thanks, Bryan ---SNIP-- add these to eval.c and definitions to ruby.h --SNIP-- VALUE rb_protect_funcall2(recv, id, argc, args, state) VALUE recv; ID id; int argc; VALUE *args; int *state; { VALUE result; int status; PUSH_TAG(PROT_NONE); if ((status = EXEC_TAG()) == 0) { result = rb_funcall2(recv, id, argc, args); } POP_TAG(); if (state) { *state = status; } if (status != 0) { return Qnil; } return result; } VALUE rb_protect_funcall3(recv, id, argc, args, state) VALUE recv; ID id; int argc; VALUE *args; int *state; { VALUE result; int status; PUSH_TAG(PROT_NONE); if ((status = EXEC_TAG()) == 0) { result = rb_funcall3(recv, id, argc, args); } POP_TAG(); if (state) { *state = status; } if (status != 0) { return Qnil; } return result; } VALUE rb_protect_require(name, state) char *name; int *state; { VALUE result; int status; PUSH_TAG(PROT_NONE); if ((status = EXEC_TAG()) == 0) { result = rb_require(name); } POP_TAG(); if (state) { *state = status; } if (status != 0) { return Qfalse; } return result; } void rb_protect_load_file(name, state) char *name; int *state; { VALUE result; int status; PUSH_TAG(PROT_NONE); if ((status = EXEC_TAG()) == 0) { rb_load_file(name); } POP_TAG(); if (state) { *state = status; } }