5 ms·
It was my experience too. What does the C API do for one? I've always found it rather unhelpful, though relatively straightforward for simple bindings. (I don't
by to3m 11y ago
It was my experience too. What does the C API do for one? I've always found it rather unhelpful, though relatively straightforward for simple bindings. (I don't like to comment about anything more involved.) But, even once you've got your own wrappers in place for converting Lua userdata objects to pointers to your custom types, and whatever, your average Lua binding still looks like this:
1. Get arguments from stack one by one
2. Call C function with arguments
3. Push result(s) to stack one by one
4. Return number of results
(You can write your own system to automate all of this this - rather more straightforward in C++ than in C - but that is hardly evidence that the C API is especially useful.)
Suppose you have a function in lua, `f(x,y)' that you want to forward to your C function, `int f(int x,double y)'. You need to do something like this:
int lua_f(lua_State *L) {
int x=luaL_checkinteger(L,1);
double y=luaL_checknumber(L,2);
int result=f(x,y);
lua_pushinteger(L,result);
return 1;
}
(It's worth having a scrabble through to see what the luaL stuff is doing internally, because some of it is string-happier than you might like. luaL_checkudata seems particularly rude. But checkinteger and checknumber seem benign enough.)
If you don't use a debugger, and you're certain you'll never need any logging or whatever, and you're sure future you won't mind having to split things all out when they are in the middle of something else and discover they need logging after all, you could do it maybe more like this:
lua_pushinteger(L,f(luaL_checkinteger(L,1),luaL_checknumber(L,2));
return 1;
But even that still doesn't strike me as particularly convenient.
- andrewmcwatters 11y agoWait, what are you people expecting from the C API? Do you not realize literally every other scripting language integration faces this exact design? At the end of the day, you will always need to take values, plug them into a function, and return that value back to to the VM if desired. Lua, Ruby, V8, you name it, they all do it. Are you expecting to magically pass a function and have some metaprogramming do everything for you? I mean this was certainly possible with LuaBind but then you suddenly take on Boost, and any experienced integrator will realize some systems quickly need more control than this.
- to3m 11y agoYes, exactly: you have to write little shim functions. I'm pretty sure this was what bdamm was complaining about, and I'm complaining about it too. I took your suggestion to be that there was some way of using the API that avoided this. There might be no better way of doing it (or maybe there might be - I have no opinion), but that wouldn't in my view automatically make the C API "remarkably excellent", "absolutely painless", nor the sort of thing that you might describe as "as easy as it is" (as were the original claims). It would just make it no more inconvenient than it has to be. Forgive me for not getting overly excited at that ;)
- pathsjs 11y agoFor instance, interfacing with c in factor works like this. You have an internal dsl that allows you to express what the signature of a c function is. It is designed to look like a function declaration in c, but it is actually valid factor. And... that's it! You can now call that function, and some meta programming drives from that pseudo signature all the information to translate values back and forth
- sitkack 11y agoLuaJIT has http://luajit.org/ext_ffi.html http://luajit.org/ext_ffi.html and Python has https://cffi.readthedocs.org/en/latest/ https://cffi.readthedocs.org/en/latest/ modeled after LuaJIT. The API for Lua is very clean for being magic free, something that cannot be said for the CPython API.