簡體   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