2012-01-17 6 views
6

estoy escribiendo una extensión de Ruby 1.9 C y quiero hacer lo siguiente en rubí:¿Cómo convierto un bloque a un proceso en una extensión Ruby 1.9 C?

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

Ahora el problema con esto es que en el método C, sólo "reciben" un bloque, y, por lo que yo sé, ni siquiera es un parámetro: sólo puedo llamar con la rb_yield.

Así que mi pregunta es: ¿hay alguna manera en una extensión Ruby 1.9 C, para transformar un bloque en un proceso o algo así, así puedo almacenarlo dentro de mi módulo y llamarlo más tarde cuando lo necesite o necesite? Como una devolución de llamada asíncrona!

ya he implementado esto con procs/lambdas, pero es igual de fea no utilizar la sintaxis del bloque directamente.

+5

Ha visto [este] artículo (http://banisterfiend.wordpress.com/2008/09/25/metaprogramming-in-the-ruby-c-api-part-one-blocks/) (especialmente "explícito bloquea el "párrafo"? Puede ser obsoleto, pero de lo contrario se parece a lo que necesita. –

+0

Lo siento, no puedo responder a su pregunta, porque yo no sé ni la API C YARV C, sino como una aclaración a otros lectores, su pregunta básicamente es: "¿cómo lo hago' definición en (y negro) end' de C ", ¿verdad? –

Respuesta

5

En la fuente de Ruby C verá esto en 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); 
} 

y Proc.new hace esto:

Crea un nuevo objeto Proc, unido al contexto actual. Proc::new pueden ser llamados sin un bloque sólo dentro de un método con un bloque adjunto, en el que caso de que el bloque se convierte en el objeto Proc.

Por lo que haría algo como esto:

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

y más tarde, para llamar al bloque de/proc:

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

Eso rb_funcall es más o menos la versión de C p.send(:call).

+0

¡Dios mío, eso fue tan simple y claro! ¡GRACIAS! – rubenfonseca

+0

@rubenfonseca: simple una vez que sabes qué hacer :) Usted necesita tener un grepping-familiaridad de la fuente C para escribir extensiones C. –

Cuestiones relacionadas