Re: FFI, cURL and function callback

  • From: Paulo Matias <syscoder@xxxxxxxxx>
  • To: luajit@xxxxxxxxxxxxx
  • Date: Sun, 24 Mar 2013 14:31:48 -0300

On Sun, Mar 24, 2013 at 1:17 PM, pingon begand <sbronfion@xxxxxxxxx> wrote:
> Thanks a lot for all your help. I know it's rather slow but I am using this
> only once. I don't know why, but it's not working for the moment, here is an
> example :

You were declaring the "option" argument of curl_easy_setopt as a
"char", which does not have sufficient size to hold the option code.
When printing the "curl_easy_setopt" function return value, you get
48, which means CURLE_UNKNOWN_OPTION (see the libcurl-errors(3)
manpage).

Also, the usage of ffi.copy is incorrect. You need to pass as its
first argument a writable memory area with sufficient size to hold the
data which will be copied.

The following code has fixes for both issues:

--

local ffi = require "ffi"

ffi.cdef[[
void *curl_easy_init();
int curl_easy_setopt(void *curl, int option, ...);
int curl_easy_perform(void *curl);
void curl_easy_cleanup(void *curl);
]]

local data = nil
function cb(ptr, size, nmemb, stream)
        local bytes = size*nmemb
        local buf = ffi.new('char[?]', bytes+1)
        ffi.copy(buf, ptr, bytes)
        buf[bytes] = 0
        data = ffi.string(buf)
        return bytes
end

fptr = ffi.cast("size_t (*)(char *, size_t, size_t, void *)", cb)

local libcurl = ffi.load("libcurl.so")

local curl = libcurl.curl_easy_init()

local CURLOPT_URL = 10002
local CURLOPT_WRITEFUNCTION = 20011

if curl then
  libcurl.curl_easy_setopt(curl, CURLOPT_URL, "http://ipv4.icanhazip.com";)
  libcurl.curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fptr)
  res = libcurl.curl_easy_perform(curl)
  libcurl.curl_easy_cleanup(curl)
end

print(data)

Other related posts: