Question

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.

Was it helpful?

Solution

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)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top