繁体   English   中英

用C编写面向Lua的函数时,检查参数是否支持表式查找的好方法是什么?

[英]When writing a Lua-facing function in C, what's a good way to check if an argument supports table-like lookups?

这是一种可能的模式,可以检查参数是否为表:

int my_fn(lua_State *L) {
  luaL_checktype(L, 1, LUA_TTABLE);
  // .. do stuff with the table ..
}

只要第一个参数是表,此方法就起作用。 但是,其他Lua类型也支持表查找,例如userdata和luajit中的cdata。

有没有一种很好的方法来检查表查找(例如通过lua_getfield )是否会在我调用它之前成功? 我的意思是不将类型限制为表格。 相关地,表,用户数据和cdata是luajit中唯一支持索引查找的类型吗?

我对仅限于Lua 5.1 C API的答案最感兴趣,因为我使用的是当前与此版本兼容的LuaJIT。

澄清

luaL_checkXXX函数的优势在于,它们可以在一行中:

  • 如果类型错误,则抛出信息丰富,用户友好的错误消息,并且
  • 提供C友好的返回值,可以立即使用。

我正在寻找类似的表。 我不期望C友好的哈希表返回值,但是如果有问题的参数不可索引,我确实希望向用户提供相同质量的错误消息。

我正在接受鸭子打字的哲学。 如果我编写的函数只是想对某个参数中的某些键编制索引,那么我不在乎该参数是否真正是一个表,或者仅仅是支持__index查找的userdata。 我要接受任何一个。

通常,只有表才具有查找功能,因为它是定义此属性的唯一类型。 用户数据是不透明的,只有主机知道如何处理或为特定行为添加一个元表(可以分析)。 CData是使用LuaJIT编译的Lua的一部分,我从来没有将此类型与C API一起使用(甚至支持它吗?)。 最后,您必须检查类型/可匹配类型以进行可能的查找,并请求一个字段来检查设置,但是lua_getfield周围没有办法(但是原始访问应该更快,请参见lua_rawget )。 例外是通过lua_objlen检查表数组的长度。

此外,更便宜的类型检查解决方案是lua_is***函数。

这是一种实现方法:

// If the value at index narg is not indexable, this function does not return and
// provides a user-friendly error message; otherwise the stack is unchanged.
static void luaL_checkindexable(lua_State *L, int narg) {
  if (lua_istable(L, narg)) return;  // tables are indexable.
  if (!luaL_getmetafield(L, narg, "__index")) {
    // This function will show the user narg and the Lua-visible function name.
    luaL_argerror(L, narg, "expected an indexable value such as a table");
  }
  lua_pop(L, 1);  // Pop the value of getmetable(narg).__index.
}

这适用于表以及在其元__index上具有__index值的任何值。

它提供了luaL_argerror给出的标准格式错误。 这是示例错误消息:

a_file.lua:7: bad argument #1 to 'fn' (expected an indexable value such as a table)

您可以像这样使用它:

// This Lua-facing function expects an indexable 1st argument.
int my_fn(lua_State *L) {
  luaL_checkindexable(L, 1);
  lua_getfield(L, 1, "key");  // --> arg1.key or nil is now on top of stack.
  // .. your fn ..
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM