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:
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. ScottI'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: