使用 Lua C API 时,熟悉虚拟堆栈非常重要——所有重要的语言边界交互都发生在那里。查看您的代码片段,您似乎没有将数据正确地整理到 C 中。
当编写 lua C 函数时,你基本上必须做 3 件事:
- 将输入的 lua 数据转换为可以在 C 中使用的数据。
- 执行处理或函数需要执行的任何操作。
- 转换并返回输出结果(如果有)返回lua。
举个例子,这就是你的findImgProxy
应该看起来像:
static int findImgProxy(lua_State *L)
{
// discard any extra arguments passed in
lua_settop(L, 1);
luaL_checktype(L, 1, LUA_TTABLE);
// Now to get the data out of the table
// 'unpack' the table by putting the values onto
// the stack first. Then convert those stack values
// into an appropriate C type.
lua_getfield(L, 1, "imagePath");
lua_getfield(L, 1, "fuzzy");
lua_getfield(L, 1, "ignoreColor");
// stack now has following:
// 1 = {imagePath="/var/image.png", fuzzy=0.5, ignoreColor=0xffffff}
// -3 = "/var/image.png"
// -2 = 0.5
// -1 = 0xffffff
const char *imagePath = luaL_checkstring(L, -3);
double fuzzy = luaL_checknumber(L, -2);
int ignoreColor = luaL_checkint(L, -1);
// we can pop fuzzy and ignoreColor off the stack
// since we got them by value
lua_pop(L, 2);
// do function processing
// ...
return 1;
}
请注意,我们必须保留imagePath
在堆栈上,因为我们持有const char *
到它。弹出该字符串将导致无效*imagePath
因为 lua 可能会收集它。
或者,您可以复制返回的字符串luaL_checkstring
进入另一个缓冲区。在这种情况下弹出字符串是可以的,因为我们不再指向 lua 拥有的内部缓冲区。
Edit:如果表中的某些键是可选的,您可以使用luaL_opt*
相反,函数并提供默认值。例如,如果fuzzy
and ignoreColor
是可选的:
// ...
const char *imagePath = luaL_checkstring(L, -3);
double fuzzy = luaL_optnumber(L, -2, 0.0); // defaults to 0.0 if no fuzzy
int ignoreColor = luaL_optint(L, -1, 0); // defaults to 0 if no ignoreColor
// ...
因此,如果调用代码为某个键提供了无意义的值,这仍然会引发错误。 OTOH,如果不存在,则该值为nil
并使用提供的默认值。