Extendig ruby: defining classes and creating objects from c

I can’t manage to define a new class (actually an exception) and then
instantiating it from C.
I define the class with:
xr_cException = rb_define_class_under(xr_module, “Exception”,
rb_eRuntimeError);
rb_define_method(xr_cException, “initialize”,
xr_cException_initialize, 4);

static VALUE xr_cException_initialize(VALUE self, VALUE status, VALUE
lasterror, VALUE function, VALUE msg)
{
rb_iv_set(self, “@status”, status);
rb_iv_set(self, “@lasterror”, lasterror);
rb_iv_set(self, “@function”, function);
rb_iv_set(self, “@msg”, msg);
return self;

At this point I can write a ruby test program like
a=MYMOD::Exception.new(1,2,3,4)
raise a, “Hello!”
and it works all right and I get output:
Test.rb:5: Hello! (MYMOD::Exception)

However if I try to do the same thing from C with:
VALUE oException, argv[4]={INT2FIX(1), INT2FIX(2), INT2FIX(3),
INT2FIX(4)};
oException = rb_class_new_instance(4, argv, xr_cException);
rb_raise(oException, “Hello!”);
I put this piece of code inside a method named raiseit and call test
from a test ruby program. I get error:
Test.rb:9:in raiseit': undefined methodnew’ for #<MYMOD::Exception:
MYMOD::Exception> (NoMethodError)

It seems that when I try to create an object of type MYMOD::Exception,
somehow ruby doesn’t find the new method. I’ve tried to define also a
new method for this class, but I get the same error.
By the way, the function rb_call_new_instance seems to be quite
undocumented…

What is the correct way to create a new object of a given class from C?

Thanks
libit

Hi,

At Sat, 20 Oct 2007 00:56:16 +0900,
An Onymous wrote in [ruby-talk:274836]:

rb_raise(oException, “Hello!”);

The first argument of rb_raise() is a class. Try:

rb_exc_raise(oException);

Hi,

At Sat, 20 Oct 2007 04:33:33 +0900,
An Onymous wrote in [ruby-talk:274879]:

rb_exc_raise(oException);

rb_exc_raise is not defined in ruby.h. At least not in the latest
version 1.8.6

It’s declared in intern.h which is included by ruby.h.

What is it? I see it defined in intern.h and called from everywhere but
I can’t find where it is defined.

In eval.c.

Thank you. Now it works.
I ended up writing an updated version of rb_raise which behaves more
like the ruby “raise” global function. That is:
myrb_raise(Qnil,NULL) behaves like “raise”
myrb_raise(Qnil,fmt,…) behaves like "raise " raising a
RuntimeError with the given message
myrb_raise(exc,NULL) behaves like "raise " where exc can be either
a class OR AN EXCEPTION OBJECT (if exc is an exception object, its
message is preserved)
and
myrb_raise(exc,fmt,…) behaves like “raise ,” that is like
the previous one but also setting the exception message.

Here it is:
VALUE myrb_raise(VALUE exc, const char *fmt, …)
{
if(!NIL_P(exc)) {
ID exception = rb_intern(“exception”);
if(!rb_respond_to(exc, exception)) rb_raise(rb_eTypeError,
“exception class/object expected”);
}
if(fmt) {
va_list args;
char buf[BUFSIZ];
VALUE msg;
va_init_list(args,fmt);
vsnprintf(buf, BUFSIZ, fmt, args);
va_end(args);
msg=rb_str_new2(buf);
if(NIL_P(exc)) exc = rb_class_new_instance(1, &msg,
rb_eRuntimeError);
else exc = rb_funcall(exc, exception, 1, msg);
}
rb_exc_raise(exc);
}

Actually the first few lines should read:
VALUE myrb_raise(VALUE exc, const char *fmt, …)
{
ID exception;
if(!NIL_P(exc)) {
exception = rb_intern(“exception”);

Oh, so ruby was looking for a “new” method not on the class but on the
instance.
This explains the problem, however how do I raise an exception from an
object?

rb_exc_raise(oException);

rb_exc_raise is not defined in ruby.h. At least not in the latest
version 1.8.6
What is it? I see it defined in intern.h and called from everywhere but
I can’t find where it is defined.

libit

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs