lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Recording of LuaJIT C FFI calls is looking good:

  double f(double, double);

but how can we make a C FFI call return multiple values?

  ffi.cdef [[ double, double swap(double, double); ]]  -- wishful thinking
  x2,y2 = ffi.C.swap(x,y)

The traditional hack of passing pointers to the C function lacks the
typical Lua interface, and wrapping it doesn't provide the efficiency
either:

  ffi.cdef [[ void swap(double, double, double*, double*); ]]
  function swap(x,y)
    local t = ffi.new'double[2]' -- warning: memory alloc not hoisted
    ffi.C.swap(x,y, t,t+1)
    return t[0], t[1]
  end

The struct return technique is closer:

  ffi.cdef [[ typedef struct { double v[2] } tuple2_t; ]]
  ffi.cdef [[ tuple2_t swap(double, double); ]]
  function swap(x,y)
    local t = ffi.C.swap(x,y)  -- NYI: unsupported C function type
    return t.v[0], t.v[1]   --a.k.a. unpack(ffi.C.swap(x,y)) ?
  end

except that we'd prefer LuaJIT to automatically do that unpacking.
Special attributes might force that behavior:

  ffi.cdef [[ void swap(double, double, __luajit_return double *,
__luajit_return double *); ]] -- blah
  ffi.cdef [[ __luajit_unpack tuple2_t swap(double, double); ]] -- hmm
  ffi.cdef [[ boost::tuple<double, double> swap(double, double); ]] -- yuck
  ffi.cdef [[ double, double swap(double, double); ]]  -- why not?

There is also the question of handling a variable number of return
values, which the fixed-sized struct return technique doesn't simply
handle.