当 C 函数被创建出来, 我们有可能会把一些值关联在一起, 也就是创建一个 C 闭包 (参见 lua_pushcclosure
); 这些被关联起来的值被叫做 上值 , 它们可以在函数被调用的时候访问的到。
无论何时去调用 C 函数, 函数的上值都可以用伪索引定位。 我们可以用 lua_upvalueindex
这个宏来生成这些伪索引。 第一个关联到函数的值放在 lua_upvalueindex(1)
位置处,依此类推。 使用 lua_upvalueindex(n)
时, 若 n 大于当前函数的总上值个数 (但不可以大于 256)会产生一个可接受的但无效的索引。
int lua_upvalueindex (int i);
返回当前运行的函数(参见 §4.4)的第 i
个上值的伪索引。
void *lua_touserdata (lua_State *L, int index);
如果给定索引处的值是一个完全用户数据, 函数返回其内存块的地址。 如果值是一个轻量用户数据, 那么就返回它表示的指针。 否则,返回 NULL
。
struct skynet_context * context = lua_touserdata(L, lua_upvalueindex(1));
void luaL_checktype (lua_State *L, int arg, int t);
检查函数的第 arg
个参数的类型是否是 t
。 参见 lua_type
查阅类型 t
的编码。
int lua_toboolean (lua_State *L, int index);
把给定索引处的 Lua 值转换为一个 C 中的布尔量( 0 或是 1 )。 和 Lua 中做的所有测试一样, lua_toboolean
会把任何不同于 false 和 nil 的值当作真返回; 否则就返回假。 (如果你想只接收真正的 boolean 值, 就需要使用 lua_isboolean
来测试值的类型。)
void lua_settop (lua_State *L, int index);
参数允许传入任何索引以及 0 。 它将把堆栈的栈顶设为这个索引。 如果新的栈顶比原来的大, 超出部分的新元素将被填为 nil 。 如果 index
为 0 , 把栈上所有元素移除。
void lua_pushcfunction (lua_State *L, lua_CFunction f);
将一个 C 函数压栈。 这个函数接收一个 C 函数指针, 并将一个类型为 function
的 Lua 值压栈。 当这个栈顶的值被调用时,将触发对应的 C 函数。
注册到 Lua 中的任何函数都必须遵循正确的协议来接收参数和返回值 (参见 lua_CFunction
)。
lua_pushcfunction
是作为一个宏定义出现的:
#define lua_pushcfunction(L,f) lua_pushcclosure(L,f,0)
void lua_rawsetp (lua_State *L, int index, const void *p);
等价于 t[k] = v
, 这里的 t
是指给定索引处的表, k
是指针 p
对应的轻量用户数据。 而 v
是栈顶的值。
这个函数会将值弹出栈。 赋值是直接的;即不会触发元方法。
userdata 类型允许将 C 中的数据保存在 Lua 变量中。 用户数据类型的值是一个内存块, 有两种用户数据: 完全用户数据 ,指一块由 Lua 管理的内存对应的对象; 轻量用户数据 ,则指一个简单的 C 指针。 用户数据在 Lua 中除了赋值与相等性判断之外没有其他预定义的操作。 通过使用 元表 ,程序员可以给完全用户数据定义一系列的操作 (参见 §2.4)。 你只能通过 C API 而无法在 Lua 代码中创建或者修改用户数据的值, 这保证了数据仅被宿主程序所控制。
int lua_rawgeti (lua_State *L, int index, lua_Integer n);
把 t[n]
的值压栈, 这里的 t
是指给定索引处的表。 这是一次直接访问;就是说,它不会触发元方法。
返回入栈值的类型。
lua_State *lua_tothread (lua_State *L, int index);
把给定索引处的值转换为一个 Lua 线程 (表示为 lua_State*
)。 这个值必须是一个线程; 否则函数返回 NULL
。
int lua_rawgetp (lua_State *L, int index, const void *p);
把 t[k]
的值压栈, 这里的 t
是指给定索引处的表, k
是指针 p
对应的轻量用户数据。 这是一次直接访问;就是说,它不会触发元方法。
返回入栈值的类型。
LUA_RIDX_MAINTHREAD: 注册表中这个索引下是状态机的主线程。 (主线程和状态机同时被创建出来。)int lua_pcall (lua_State *L, int nargs, int nresults, int msgh);
以保护模式调用一个函数。
nargs
和 nresults
的含义与 lua_call
中的相同。 如果在调用过程中没有发生错误, lua_pcall
的行为和 lua_call
完全一致。 但是,如果有错误发生的话, lua_pcall
会捕获它, 然后把唯一的值(错误消息)压栈,然后返回错误码。 同 lua_call
一样, lua_pcall
总是把函数本身和它的参数从栈上移除。
如果 msgh
是 0 , 返回在栈顶的错误消息就和原始错误消息完全一致。 否则, msgh
就被当成是 错误处理函数 在栈上的索引位置。 (在当前的实现里,这个索引不能是伪索引。) 在发生运行时错误时, 这个函数会被调用而参数就是错误消息。 错误处理函数的返回值将被 lua_pcall
作为错误消息返回在堆栈上。
典型的用法中,错误处理函数被用来给错误消息加上更多的调试信息, 比如栈跟踪信息。 这些信息在 lua_pcall
返回后, 由于栈已经展开,所以收集不到了。
lua_pcall
函数会返回下列常数 (定义在 lua.h
内)中的一个:
LUA_OK (0): 成功。
LUA_ERRRUN: 运行时错误。
LUA_ERRMEM: 内存分配错误。对于这种错,Lua 不会调用错误处理函数。
LUA_ERRERR: 在运行错误处理函数时发生的错误。
LUA_ERRGCMM: 在运行 __gc 元方法时发生的错误。 (这个错误和被调用的函数无关。)
---------------------------