skynet lua服务常用API

4.4 – C闭包

当 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)); 

  1. // 完成服务的实例化,执行服务lua代码  
  2. static int  
  3. _init(struct snlua *l, struct skynet_context *ctx, const char * args, size_t sz) {  
  4.     lua_State *L = l->L;  
  5.     l->ctx = ctx;  
  6.     lua_gc(L, LUA_GCSTOP, 0);  
  7.     lua_pushboolean(L, 1);  /* signal for libraries to ignore env. vars. */  
  8.     lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV");  
  9.     luaL_openlibs(L);  
  10.     lua_pushlightuserdata(L, ctx);  
  11.     lua_setfield(L, LUA_REGISTRYINDEX, "skynet_context");  

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 是栈顶的值。

这个函数会将值弹出栈。 赋值是直接的;即不会触发元方法。

  1. static int  
  2. _callback(lua_State *L) {  
  3.     struct skynet_context * context = lua_touserdata(L, lua_upvalueindex(1));  
  4.     int forward = lua_toboolean(L, 2);  
  5.     luaL_checktype(L,1,LUA_TFUNCTION); // 取到上述c.callback(F)的F  
  6.     lua_settop(L,1);  
  7.     lua_rawsetp(L, LUA_REGISTRYINDEX, _cb); // 记录lua函数F到_cb这个索引位置 _cb:static int _cb(...)  

       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: 注册表中这个索引下是状态机的主线程。 (主线程和状态机同时被创建出来。)
LUA_RIDX_GLOBALS: 注册表的这个索引下是全局环境。

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 元方法时发生的错误。 (这个错误和被调用的函数无关。)



---------------------------

 



  • dispatch(type, func) 为 type 类型的消息设定一个处理函数。
  • dispatch_message(typeid, msg, sz, session, source) 默认的消息处理过程,由 C 层传递给它消息的五元组:消息类型 id 、指针、长度、session 号、消息源地址。
  • ret(msg, sz) 将打包好的消息回应给当前任务的请求源头。
  • retpack(...) 将消息用 pack 打包,并调用 ret 回应。
  • response([packfunc]) 生成一个回应函数,用于在将来回应当前任务。当消息不使用默认的 lua 类型时,需提供对应的消息打包函数。
  •  error(msg) 向 log 服务发送一条消息。
  •  launch(name, ...) 直接启动一个 C 服务.
  •  register(name) 给当前服务起一个字符串名。
  •  timeout(time, func) 设定一个定时触发函数 func ,在 time * 0.01s 后触发。
  •  init_service(func) 用 func 函数初始化服务。
  •  void luaL_checktype (lua_State *L, int arg, int t);
    检查函数的第 arg 个参数的类型是否是 t。 参见 lua_type 查阅类型 t 的编码。
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  

若参数endptr不为NULL,则会将遇到不合条件而终止的nptr中的字符 指针 由endptr返回;若参数endptr为NULL,则会不返回非法字符串。

你可能感兴趣的:(skynet)