How does one handle Ruby 2.0.0 keyword arguments from a C extension?
Background
def example(name: 'Bob' hat_color: 'red')
puts "#{name} has a #{hat_color} hat!"
end
example #=> "Bob has a red hat!"
example(name: 'Joe', hat_color: 'blue') #=> "Joe has a blue hat!"
Keyword arguments (like the above) are quite useful when handling methods that have a lot of different call sequences or options. I have one such method in a C extension (a blit
method that handles most of the OpenGL drawing in my project) and I am wondering how I might have the method handle keyword arguments from ruby.
Ideas
Based on some research I have done, I think that such handling might be done through the :
option on the rb_scan_args
C function. However, I have been unable to find any information on how to use it to do so.
There is no core method that currently uses keyword arguments directly, i.e.
klass.instance_method(:method).parameters
will never return:key
for builtin classes.You probably have to define a method that accepts an argument, in this case a hash and parse it yourself. To do so, you can use
rb_scan_args
with the:
argument to get aHash
from the last argument (e.g.dir_initialize
) or code similar to theOPTHASH_GIVEN_P
macro (inarray.c
). From the hash, you could userb_get_kwargs
to get the values you want. I haven't looked into how to generate an error for unrecognized keyword arguments if you desire. I think most core methods don't do this check (at least yet).You could have your method defined in Ruby using the keyword elements and call an internal C method from there. This would give you for free unknown keys being checked and a proper
parameters
signature.I hope to improve this situation with a revised api to define methods in Ruby 2.2 that would make it more natural to have keyword arguments in C functions, among other things (see this issue)