When capturing blocks, the type of the arguments and return type
must be specified in the capturing method block signature.

Passing a Proc to a C function

Passing a Proc to a C function, for example as a callback, is possible
as long as the Proc isn't a closure. If it is, either a compile-time or
runtime error will happen depending on whether the compiler can check this.
The reason is that a Proc is internally represented as two void pointers,
one having the function pointer and another the closure data. If just
the function pointer is passed, the closure data will be missing at invocation time.

Most of the time a C function that allows setting a callback also provide
an argument for custom data. This custom data is then sent as an argument
to the callback. For example, suppose a C function that invokes a callback
at every tick, passing that tick:

To properly define a wrapper for this function we must send the Proc as the
callback data, and then convert that callback data to the Proc and finally invoke it.

moduleTicker# The callback for the user doesn't have a Void*
@@box : Pointer(Void)?
defself.on_tick(&callback : Int32 ->)
# Since Proc is a {Void*, Void*}, we can't turn that into a Void*, so we# "box" it: we allocate memory and store the Proc there
boxed_data =Box.box(callback)
# We must save this in Crystal-land so the GC doesn't collect it (*)
@@box = boxed_data
# We pass a callback that doesn't form a closure, and pass the boxed_data as# the callback dataLibTicker.on_tick(->(tick, data) {
# Now we turn data back into the Proc, using Box.unbox
data_as_callback =Box(typeof(callback)).unbox(data)
# And finally invoke the user's callback
data_as_callback.call(tick)
}, boxed_data)
endendTicker.on_tick do|tick|
puts tick
end

Note that we save the box in @@box. The reason is that if we don't do it,
and our code doesn't reference it anymore, the GC will collect it.
The C library will of course store the callback, but Crystal's GC has
no way of knowing that.