On 22 March 2016 at 08:34, Tim Hill <drtimhill@gmail.com> wrote:
[A] Design the C function to not use state, or not call any Lua APIs while it holds resources/state. This results in very strange contorted code even when it is possible.
[B] Compile Lua for C++ so that it uses exceptions and not longjmp, and then use try() clauses to inject “finally” handling to clean up resources. This of course is only viable when C++ is available, and assumes that Lua uses exceptions in a manner that allows that to work (I’ve not studied this in detail).
[C] Allocate the stateful structure as a Lua full userdata, and then use __gc() to perform cleanup when Lua collects the abandoned structure (essentially a dispose() model).
[D] Have a dummy “outer” C function that then does a lua_pcall() into the (inner) real C function, so that Lua errors are caught and the state can be cleaned up before the outer C function either returns or re-throws the Lua error.
I'm usually okay with A, C or D.
However there is one exception: APIs that allocate an object for you.
e.g. imagine an API that returns a freshly allocated string for you,
e.g. it does (in C) `return strdup(buffer_on_stack)`
==> How do you bind this to lua?
- Using lua_pushstring directly would throw on OOM, and not free the string.
- There is no way to reliably pre-allocate space for a string
(ALTERNATIVE FIX POSSIBLE HERE)
- Allocating an object to use __gc on it isn't fast or flexible.
It also changes your coding style as it's hard to share a
metatable between functions.