Comment by kragen
1 year ago
With Python's extension API, you have to carefully incref and decref Python values to ensure that you don't either leak memory or deallocate data that's still in use. That's what the Lua stack interface saves you. It's not a call stack, which seems to be what you're thinking of.
Lifetimes and references are things to consider in Lua integration code too. See luaL_ref() rationale and why you can’t lua_pop() a string that is in use. The fact that gc doesn’t happen instantly 99.99999% of the times doesn’t save you from thinking about it.
Not that this was a hard topic in a language where lifetimes are the main concern and business as usual. In C/etc you can’t hold anything without a ref or some sort of a lifetime guarantee. What makes it special wrt Lua/Python?
Yeah, I didn't mean to say you didn't have to think about lifetimes at all when embedding Lua, just that the stack, weird as it is, seems to simplify that kind of thing rather than complicating it (even if you do occasionally have to luaL_ref). But if there's a clearly better alternative, I'd like to know about it. Constantly calling Py_INCREF and Py_DECREF isn't it.
Delayed GC seems like it might add headaches for this kind of thing rather than removing them, because your bugs may take a while to show up in testing.
Lua stack basically works as an arena if you aren’t eager to clean it.
I guess in C one could macro hack himself a similar arena to borrow objects from python runtime.
In C++ it’s a matter of befriending a smart pointer with ref/unref calls. It was probably done hundreds of times in all sorts of python embedding wrappers.
Indeed, but the rules for doing so are straightforward and easy to apply almost mechanically. Indeed, if you are writing in C++ or Rust, you just use a smart pointer that does it for you.