lua-users home
lua-l archive

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


On Mon, Oct 16, 2006 at 02:21:19PM -0500, Rici Lake wrote:
> That would be the suggestion if you were using a C++ program with 
> exceptions. If you're not, then Lua error handling with C++ is no 
> different than Lua error handling with C: to wit, if you acquire 
> resources and then use a Lua API which might throw a Lua error, you 
> must use lua_pcall or lua_cpcall in order to trap the error so that you 
> can release the resources. (Alternatively, you can make sure that the 
> resources are part of a Lua userdata with an appropriate __gc 
> metamethod.)

An actual binding:

        static int SetSongOptions( T* p, lua_State *L )
        {
                ModsLevel m = Enum::Check<ModsLevel>( L, 1 );

                SongOptions so;

                so.FromString( SArg(2) );
                p->m_SongOptions.Assign( m, so );
                return 0;
        }

SArg(2) is shorthand for "lua_checkstring(L, 2), and convert to a std::string".
It might error; if that happens, SongOptions will leak.

I could write it like this (which may also not be portable, but is
definitely better):

        static int SetSongOptions( T* p, lua_State *L )
        {
                ModsLevel m = Enum::Check<ModsLevel>( L, 1 );
                size_t iOptionsSize;
                const char *pOptions = luaL_checklstring( L, 2, &iOptionsSize );

                // everything that might trip Lua errors above; all C++
                // ctors below
                std::string sOptions( pOptions, iOptionsSize );
                SongOptions so;

                so.FromString( sOptions );
                p->m_SongOptions.Assign( m, so );
                return 0;
        }

but this is cumbersome here and worse in the general case (we have helpers
like SArg for a reason: there are lots of them).  It's also hard to know
if it's correct; there's no way to get a compiler warning if it's wrong.

I suppose I could try something like this:

        static int SetSongOptions( T* p, lua_State *L )
        {
                ModsLevel m = Enum::Check<ModsLevel>( L, 1 );
                luaL_checkstring( L, 2 );

                // ...

                so.FromString( SArg(2) );
         }

where SArg is unlikely to error, since it checked the type and did any
string conversion already.  But this is just working around one source
of errors; errors detected during less trivial traversals are harder to
check in advance.  (Like the above, it's also hard to check for correctness.
Since they would be problems that would compile silently, manifest as
small memory leaks, and only happen as a result of uncommon Lua errors,
this would be a persistant source of small, hard to fix code errors.)

(As an aside, I'm not worried about OOM errors; popping up a dialog and
dying is acceptable here.  It's the other more common, less fatal errors
that would be nice to handle properly.)

-- 
Glenn Maynard