I’m trying to write a C extension to ruby that’ll generate a class. I’m looking on how to define some default arguments to a class. For example, if I have this class decleration in ruby:
class MyClass
def initialize(name, age=10)
@name = name
@age = age
end
end
You can initialize it with mc = MyClass.new("blah"), and the age parameter will be set internally. How do I do this in C? So far I got this, but this forces entering the other argument:
require "ruby.h"
static VALUE my_init(VALUE self, VALUE name, VALUE age)
{
rb_iv_set(self, "@name", name);
rb_iv_set(self, "@age", age);
return self;
}
VALUE cMyClass;
void Init_MyClass()
{
// create a ruby class instance
cMyClass = rb_define_class("MyClass", rb_cObject);
// connect the instance methods to the object
rb_define_method(cMyClass, "initialize", my_init, 2);
}
I thought about checking the value of age against Qnil or using if ( TYPE(age) == T_UNDEF ), but I just get segfaults from there. Reading through README.EXT leads me to believe I can accomplish this through rb_define_method using the value of argc, but this wasn’t too clear. Any ideas? Thanks.
You’re right – you can do this using
rb_define_methodand a negative value forargc.Normally
argcspecifies the number of arguments your method accepts, but using a negative value specifies that the method accepts a variable number of arguments, which Ruby will pass in as an array.There are two possibilities. First, use
-1if you want the arguments passed in to your method in a C array. Your method will have a signature likeVALUE func(int argc, VALUE *argv, VALUE obj)whereargcis the number of arguments,argvis a pointer to the arguments themselves, and obj is the receiving object, i.e.self. You can then manipulate this array as you need to mimic default arguments or whatever you need, in your case it might look something like this:The alternative is to have a Ruby array passed into your method, which you specify by using
-2in your call torb_define_method. In this case, your method should have a signature likeVALUE func(VALUE obj, VALUE args), whereobjis the receiving object (self), andargsis a Ruby array containing the arguments. In your case this might look something like this: