LUAMOD_API int luaopen_string(lua_State *L){
luaL_newlib(L, strlib);
createmetatable(L);
return l;
}
这里多了一处createmetatable的调用,下面列出细节:
static void createmetatable (lua_State *L){
lua_createtable(L, 0, 1); /*table to be metatable for strings*/
lua_pushliteral(L, ""); /*dummy string*/
lua_pushvalue(L, -2); /*copy table*/
lua_setmetatable(L, -2); /*set table as metatable for strings*/
lua_pop(L, 1); /*pop dummy string */
lua_pushvalue(L, -2); /* get string library*/
lua_setfield(L, -2, "__index");/*metatable.__index = string*/
lua_pop(L, 1) /* pop metatable */
}
第一次看Lua的API使用流程,容易被Lua Stack弄晕。Lua和C的交互就是通过这一系列的API操作Lua栈来完成的。如果你看不太明白,可以用笔在纸上画出Lua栈上数据的情况。进入这个函数时,栈顶有一个table、即所有的string API存在的那张表。然后,余下的几行API创建了一个metatable,使用这张表做索引表。这张元表最终被设置入dummy字符串中。/* macro to ‘unsign’ a character */
#define uchar(c) ((unsigned char)(c))
static size_t posrelat (ptrdiff_t pos, size_t len){
if(pos >= 0) return (size_t) pos;
else if(0u - (size_t)pos > len) return 0;
else return len - ((size_t) - pos) + 1;
}
lstrlib.c中间的数百行代码大体分为三个部分。
第一部分,是一些简单的API实现,如string.len, string.reverse,string.lower, string.upper等等,实现的中规中矩,乏善可陈。str_byte函数的实现中,有一行luaL_checkstack调用值得初学Lua的C binding、编写人员注意。Lua的栈不像C语言的栈那样,不大考虑栈溢出的情况。Lua栈给C函数留的默认空间很小,默认情况下只有20(LUA_MINSTACK定义在lua.h中,默认值为20)。当你要在Lua的栈上留下大量值时,务必用luaL_checkstack扩展堆栈。因为处于性能考虑,Lua和栈有关的API都是不检查栈溢出的情况的。
if (posi + n <= pose) /* (size_t->int) overflow */
return luaL_error(L, "string_slice_too_long");
luaL_checkstack(L, n, "string_slice_too_long");
for (i = 0; i