Ruby Keyword Arguments in C Extensions

540 views Asked by At

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.

1

There are 1 answers

1
Marc-André Lafortune On BEST ANSWER

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 a Hash from the last argument (e.g. dir_initialize) or code similar to the OPTHASH_GIVEN_P macro (in array.c). From the hash, you could use rb_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)