jmckaskill / luaffi

Standalone FFI library for calling C functions from lua. Compatible with the luajit FFI interface.
469 stars 84 forks source link

Casting and calling a vararg function #35

Closed daurnimator closed 12 years ago

daurnimator commented 12 years ago

I noticed that casting didn't work how it does in luajit. When calling a vararg function, the casts don't seem to do the correct thing. Consider a short example that sets a file descriptor as non-blocking:

local bit = require "bit"
local ffi = require "ffi"
ffi.cdef[[extern int fcntl (int __fd, int __cmd, ...);]]

F_GETFL = 3
F_SETFL = 4
O_NONBLOCK = tonumber("04000",8)

local fd = 0
local flags = ffi.C.fcntl(fd,F_GETFL)
flags = bit.bor ( flags , O_NONBLOCK )
ffi.C.fcntl ( fd , F_SETFL , ffi.cast("int",flags) )

assert( ffi.C.fcntl(fd,F_GETFL) == flags )

Looking via strace, this is actually doing:

fcntl(0, F_GETFL)                       = 0x8402 (flags O_RDWR|O_APPEND|O_LARGEFILE)
fcntl(0, F_SETFL, O_RDWR|O_EXCL|O_NOCTTY|O_TRUNC|O_APPEND|O_NONBLOCK|O_LARGEFILE|0x20) = 0
fcntl(0, F_GETFL)                       = 0x8c02 (flags O_RDWR|O_APPEND|O_NONBLOCK|O_LARGEFILE)
jmckaskill commented 12 years ago

I think I know what's going on. The return of ffi.cast is a lua number. Thus it gets converted to a double in the vararg. ffi.cast('int', x) should return a boxed int.

You should be able to use ffi.cast('uintptr_t') for now.

jmckaskill commented 12 years ago

This was actually caused by #40 where the tonumber('04000', 8) was being parsed as base 10.