Search code examples
luaffiluajit

Using luajit ffi to convert variable args to a char* const[] for execvp


Given a function like exec, how do I call it from lua ffi given an unknown number of arguments.

The function prototype being:

int execv(const char *path, char *const argv[]);

i.e.

function myexecv(...)
     local arg = { ... }
     local carg = ffi.new("char *const[?]", #arg)
     for i = 1, #arg do
        carg[i-1] = arg[i]
     end
     return ffi.C.execv(carg[0], carg)
end

Which doesn't work.

cannot convert 'string' to 'char *const'

I thought there might be a short cut way of initializing or creating something I can pass into argv. How do I do that?


Solution

  • I think I have figured it out and it seems to work.

    I looked at another library and found a different way of calling ffi.new and expanded that slightly. Also because of the type you couldn't convert a string directly so I first create it as a normal const char*. And pass the length + 1 (to null terminate it). Then pass arg as the initializer. Then recast it to the correct type before calling the real execv.

    function myexecv(...)
        local arg = {...}
        arg = ffi.new("const char*[?]", #arg+1, arg)
        arg = ffi.cast("char *const*", arg)
        return ffi.C.execv(arg[0], arg)
    end
    

    Well, the above did work at some point. But stopped working. I kept getting "Bad Address" errors. It would seem that the copy operation for ffi.new wasn't working as expected. So I've changed the code to the following and this does work reliably.

    function myexecv(...)
        local arg = {...}
        local argv = ffi.new("const char*[?]", #arg+1, arg)
        argv[#arg] = nil
        return ffi.C.execv(argv[0], argv)
    end