Subject:
Re: [ruby-ffi] Passing a String Pointer to Callback Procs -- How to append?
From:
Wayne Meissner
Date:
11/9/10 7:56 PM
To:
ruby-ffi@googlegroups.com

You can't pass ruby objects through C callbacks with FFI, so any
variables you want to access from the callback have to be visible to
the Proc when you create it.

You seem to be mostly doing it correct with your data_handler() method
- i.e. the _string parameter to data_handler() will be visible inside
the proc callback, and you can just append the data to it.  The
handler parameter to the callback will not be used (and is most likely
nil anyway).

I would change the first parameter (stream) of the curl handler to be
of type pointer though, and get the data out like so:

   _string << stream.get_string(0, size)

I'm not sure if curl guarantees that the buffer is NUL terminated, but
I suspect not, since it is binary data, so you only want to copy out
as many bytes as curl indicates are ready (the size param).

One _VERY_ important thing to remember, always keep a reference to the
proc returned by data_handler somewhere - e.g. as an @variable in each
Request instance.  FFI dynamically generates native code for the
callback, and you need to keep a strong reference to it to avoid it
being prematurely collected, and crashing the VM.  Stashing the proc
somewhere for the lifetime of the Request instance should suffice.


On 9 November 2010 10:30, Scott Gonyea <gonyea@gmail.com> wrote:
> I'm having a really painful time figuring this out.  I jumped onto
> what NoKarma had already begun, with his curl-ffi library, and started
> running with it.  I'm trying to emulate the ruby extension layers used
> in some different Curl gems (Streamly and Patron, atm).
>
> Curl wants you to pass a method reference, which it will then
> callback.  You can see examples used in Streamly and Patron:
>
> Streamly, lines 29-83:
> https://github.com/aitrus/streamly/blob/master/ext/streamly.c#L29
>
> Patron, lines 59-75 (Much simpler):
> https://github.com/aitrus/patron/blob/master/ext/patron/session_ext.c#L59
>
> Basically, they're allocating a buffer and providing a callback + that
> buffer, which is sent to the callback. I've added this callback to
> CurlFFI and I have the Proc working, etc... But I cannot seem to get
> it to append to the string.
>
> Callback Additions to CurlFFI:
> https://github.com/aitrus/curl_ffi/blob/master/lib/bindings.rb#L923
> https://github.com/aitrus/curl_ffi/blob/master/lib/bindings.rb#L926
>
> I'll delete 926, as it's not necessary (I think).
>
> Procs that get called:
> https://github.com/aitrus/streamly/blob/master/lib/streamly/request.rb#L11
>
> I suppose the last resort can be to call C libraries, allocating /
> freeing a string.  But that makes me think I'm doing it wrong.  I
> can't imagine that I'm doing anything overly interesting with my code.
>
> Scott
>