'Ruby and C API: rb_funcall_with_block on global method? How to call ruby global method with block from C?

I want to call a global method in ruby from my C API code. So in ruby:

def giveMeABlock(*args)
  puts "Starting giveMeABlock with #{args.inspect}"
  yield if block_given?
end

As I've since learned, global functions are actually just private functions in Object, so we can call them from anywhere.

And in C I want to call this method, I can do use rb_funcallv:

VALUE rb_funcallv(VALUE recv, ID mid, int argc, VALUE *argv)
Invokes a method, passing arguments as an array of values. Able to call even private/protected methods.

For this specific example I can do:

rb_funcallv(self, rb_intern("giveMeABlock"), 0, NULL);

And we are able to call the method, though no block is supplied.

To call with a block we have:

VALUE rb_funcall_with_block(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE passed_procval)
Same as rb_funcallv_public, except passed_procval specifies the block to pass to the method.

But this, like rb_funcallv_public, can only call public methods. Which means if I try:

rb_funcall_with_block(self, rb_intern("giveMeABlock"), 0, NULL, block);

I get:

private method `giveMeABlock' called for main:Object (NoMethodError)

So why is there no funcall for private methods that can provide a block, or am I missing something? And how do I accomplish this seemingly simple task?

I have realized that I can define the method inside the Object class and then it works (since now it's public), but this seems hacky and assumes I have the ability to alter the ruby source.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source