How to convert a block in Proc to a Ruby 1.9 C extension?

I am writing a Ruby 1.9 C extension and I want to do the following in ruby:

notifier = Notifier.new notifier.on 'click' do puts "clicked!" end 

Now the problem with this is that in method C I only “get” the block, and as far as I know, this is not even a parameter: I can just call with rb_yield .

So my question is: is there a way to extend Ruby 1.9 C to convert a block to proc or something like that, so I can save it inside my module and call it later when I want / As an asynchronous callback!

I already implemented this with Procs / lambdas, but it's just ugly not to use the block syntax directly.

+6
source share
1 answer

In the Ruby C source, you will see this in proc.c :

 /* * call-seq: * proc { |...| block } -> a_proc * * Equivalent to <code>Proc.new</code>. */ VALUE rb_block_proc(void) { return proc_new(rb_cProc, FALSE); } 

and Proc.new does the following:

Creates a new Proc object bound to the current context. Proc::new can be called without a block only inside a method with an attached block, in which case this block is converted to a Proc object.

So you would do something like this:

 VALUE p = rb_block_proc(); /* and then store `p` somewhere convenient */ 

and then later to call the / Proc block:

 rb_funcall(p, rb_intern("call"), 0); 

This rb_funcall is pretty much a version of C p.send(:call) .

+5
source

Source: https://habr.com/ru/post/906240/


All Articles