From: senderista@... (Tobin Baker) Date: 2001-07-15T14:07:29+09:00 Subject: [ruby-talk:17864] Trapping Ruby exceptions from C I'm trying to solve the problem of how to trap a Ruby exception from a C call to a Ruby method. (Specifically, I'm writing server-side CORBA bindings which unmarshal an incoming request and dynamically dispatch it to a Ruby servant object registered with the ORB.) The code for this is completely generic; it has no idea what methods it's calling or what exceptions these might raise. What it needs to do is get a copy of the exception raised so it can marshal it over the wire back to the client. Right now I'm using rb_rescue for the method call, along with a helper class to hold any exception raised. The code looks like this: class ErrorHolder def initialize(error=nil) unless error.nil? raise TypeError unless error.kind_of?(StandardError) end @error = error end end // wrapper for rb_apply, necessary since all arguments for a function passed to rb_rescue must be packed into a single array static VALUE rorbit_apply_try(VALUE packed_args) { int argc; VALUE *argv; VALUE recv; VALUE sym; VALUE args; Check_Type(packed_args, T_ARRAY); argc = RARRAY(packed_args)->len; argv = RARRAY(packed_args)->ptr; rb_scan_args(argc, argv, "3", &recv, &sym, &args); Check_Type(args, T_ARRAY); return rb_apply(recv, SYM2ID(sym), args); } // Use as second function pointer to rb_rescue (with error_holder used by caller to retrieve error value) static VALUE rorbit_trap_exception(VALUE error_holder, VALUE error) { if (!RTEST(rb_obj_is_kind_of(error, rb_eStandardError))) rb_iv_set(error_holder, "@error", rb_class_new_instance(0, 0, rb_eTypeError); else rb_iv_set(error_holder, "@error", error); return Qnil; } This is the code that calls an arbitrary method on the Ruby servant using rb_apply: // use rb_rescue to catch exception VALUE packed_args = rb_ary_new3(3, servant->impl, ID2SYM(rb_intern(name)), args); VALUE error_holder = rb_class_new_instance(0, 0, rorbit_c_CORBA_ORBit_ErrorHolder); results = rb_rescue(rorbit_apply_try, packed_args, rorbit_trap_exception, error_holder); error = rb_iv_get(error_holder, "@error"); Is there a way to retrieve an exception from the method called by rb_apply without having to use a helper class? I was frankly surprised there wasn't a simpler way to do it, since this is something C extensions would have to do all the time. Am I missing something obvious?