Warden wrote:
> I'm working on doing some embedding work and I have a function defined 
> in C, callable in ruby that has a few default parameters.  The problem 
> is that I'm not sure how to tell ruby via the C API that the last 
> parameters should default to nil or 0 or whatever if they're not used.
> 
> In the mean time I can't call the "short" version of the function 
> because it complains about an unmatching number of parmeters.  Is there 
> any way to specify default values from within C?

Are you using -1 as your argc in rb_define_method? Using -1 asks the 
intepreter to pass a variable number of args in a C array.

In that case you can use rb_scan_args to unpack the array, but I don't 
know of any simple way to assign defaults. To avoid doing this manually, 
the cgen library (see RAA) gives you a 'default' specifier (as well as a 
'typecheck' specifier and an interface to all the functionality of 
rb_scan_args). Each default specifier can be a C expression, and it may 
refer to previous args.

Here's an example (taken from examples/sample.rb):

# snip...

lib2.define_singleton_method(Point, :test).instance_eval {
   c_array_args {
     required  :arg0, :arg1
     optional  :arg2, :arg3, :arg4
     typecheck :arg2 => Numeric, :arg3 => Numeric
     default   :arg3 => "INT2NUM(7)",
               :arg4 => "INT2NUM(NUM2INT(arg2) + NUM2INT(arg3))"
     rest      :rest
     block     :block
   }
   body %{\
     rb_funcall(block, #{declare_symbol :call}, 6,
                arg0, arg1, arg2, arg3, arg4, rest);
   }
   # returns nil by default
}

# snip...

tester = proc { |arg0, arg1, arg2, arg3, arg4, rest|
   argstrs = [arg0, arg1, arg2, arg3, arg4, rest].map { |arg|
     arg.inspect
   }
   printf "test args are: %s, %s, %s, %s, %s, %s\n", *argstrs
}

Point.test(0, 1, 2, &tester)
Point.test(0, 1, 2, 3, &tester)
Point.test(0, 1, 2, 3, 4, &tester)
Point.test(0, 1, 2, 3, 4, 5, &tester)
Point.test(0, 1, 2, 3, 4, 5, 6, &tester)

# output:

test args are: 0, 1, 2, 7, 9, []
test args are: 0, 1, 2, 3, 5, []
test args are: 0, 1, 2, 3, 4, []
test args are: 0, 1, 2, 3, 4, [5]
test args are: 0, 1, 2, 3, 4, [5, 6]