lua-users home
lua-l archive

Re: Exceptions from lua_getfield with __index metamethod

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


2011年10月28日 Bryan McGinty <bmcginty@silverspringnet.com>:
> I am writing Lua library code in C.  I am attempting to
> determine if a global object exists, and if it does has
> a particular key.
>
> I first determine if the global object exists using:
> lua_getglobal(ls, module);
> if (lua_isnil(ls, -1) == 0) {
>
> If the object exists and a key has been specified I then
>
> attempt to determine if the key exists using:
> lua_getfield(ls, -1, key);
>
> With this call the object's __index metamethod is called.
> If the __index metamethod returns an argument error my
> code terminates.
>
> Is there a better way to be doing this operation?  If not,
> how can I catch the exception?
You have to wrap the code that can generate the exception in a
protected call. In C it's done with lua_pcall or lua_cpcall. In your
case you would replace code like this:
const char* get_foo_bar(lua_State* L)
{
 const char* name;
 // Lua part, may throw
 lua_getglobal(L, "foo");
 if (!lua_isnil(L, -1))
 {
 lua_getfield(L, -1, "bar");
 if (lua_isstring(L, -1))
 name = strdup(lua_tostring(L, -1));
 lua_pop(L, 1); // pop foo.bar or nil
 }
 lua_pop(L, 1); // pop foo or nil
 // C part, safe
 name = adjust_name(name);
 return name;
}
with code like this:
struct context_t
{
 const char* name;
};
const char* get_foo_bar2(lua_State* L)
{
 context_t context;
 const char* name;
 // protect the Lua part
 lua_cpcall(L, get_foo_bar2_helper, &context);
 name = context.name;
 // C part stays the same
 name = adjust_name(name);
 return name;
}
int get_foo_bar2_helper(lua_State* L)
{
 context_t* context;
 const char* name;
 context = lua_touserdata(L, 1);
 lua_getglobal(L, "foo");
 if (!lua_isnil(L, -1))
 {
 lua_getfield(L, -1, "bar");
 if (lua_isstring(L, -1))
 name = strdup(lua_tostring(L, -1));
 lua_pop(L, 1); // pop foo.bar or nil
 }
 lua_pop(L, 1); // pop foo or nil
 context.name = name;
 return 0;
}

AltStyle によって変換されたページ (->オリジナル) /