在lua中,字符串的第一个字符的索引是1,也可以使用负数索引,这样将从字符串的尾部开始计数,索引-1代表字符串最后一个字符。 



 %a+ (alphabet)字母 +表示匹配一个或者多个 

 %c      控制字符 

 %d      数字 

 %l       小写字母 

 %p     标点字符 

 %s     空白字符 

 %u     大写字母 

 %w    字母和数字字符 

 %x    十六进制数字 

 %z    内部表示为0的数字 

 分类的大写形式表示它们的补集 



 + 重复一次或多次 

 * 重复0次或多次 

 - 重复0次或多次 

 ?可选部分,0或1次 



 如果不能确定变量对应的是字符串,则可以考虑使用tostring。 

 捕获功能可以根据一个模式从目标字符串中抽出匹配于该模式的内容,在指定捕获时,应将模式中需要捕获的部分写到一对园括号内. 

 模式匹配尽可能精确,以防止影响效率。 



 io.read从当前输入文件中读取字符串,它的参数有: 

 "*all"  读取整个文件 

 "*line" 读取下一行 

 "*number" 读取一个数字 

 <num>   读取一个不超过<num>个字符的字符串 

 io.read(0)是一个特殊情况,用于检查是否到达了文件末尾,如果还有数据可以读取,则返回一个空字符串,否则返回nil。 

 如果需要在模式字符串中包含值为零的字节,可以用转义字符%z来表示。 



 调试库由两类函数组成:自省函数(introspecive function)和钩子(hook)。自省函数允许检查一个正在运行中程序的各个方面,钩子则允许跟踪一个程序的执行。 

 在调试库中有一个重要的概念"栈层(stack level)"。一个栈层是一个数字,它表示某一时刻某个活动的函数,即一个已被调用但尚未返回的函数。调用调试库的函数是层1,调用这个函数的函数是层2.依次类推。 

 debug.getinfo函数。获取一个包含对应函数相关信息的table,P197 

 debug.getlocal用来检查任意活动函数的局部变量。 P199 

 debug.getupvalue 用来获取一个非局部变量 P200 

 调试库中所有自省函数都接受一个可选的协同程序参数作为第一个参数,这样就可以从外部来检查这个协同程序。 Ps:5.1之后的新特征。 

 对协同程序调用traceback追溯没有进行到resume调用,因为协同程序和主程序运行在不同的栈上。 



 钩子 函数 P219 

 四类事件触发钩子函数  call事件,return 事件,line事件以及count事件。 

 sethook用来注册一个钩子,需要两个到3个参数来调用。第一个参数是钩子函数,第二个参数是一个字符串,描述需要监控的事件,第三个参数是一个可选数字,用于说明多久获得一次count事件。需要关闭钩子,只需不带任何参数调用sethook。 



 做计时性的剖析,最好使用C接口,因为lua调用钩子代价很高,从而使得测试结果偏差较大。 



 C API是一组能使C代码与Lua交互的函数。 

 Lua与C语言通信的主要方法是一个无所不在的虚拟栈,几乎所有的API调用都会操作这个栈上的值。栈可以解决Lua和C语言之间存在的两大差异,第一种差异是Lua使用垃圾收集,而C语言要求现实地释放内存,第二种是Lua 

 使用动态类型,而C语言使用静态类型。 

 P208 



 如果将Lua作为C代码来编译,并在C++中使用它,可以包含lua.hpp来代替lua.h。lua.hpp定义为: 

 extern "C"{ 

#include "lua.h" 

 } 



 lua持有的字符串,都会生成一个内部副本或者复用现有的内容。 

 不要在C函数之外使用在C函数内获得的指向Lua字符串的指针。(当lua调用的一个C函数返回时,Lua就会清空它的栈。) 

 lua_checkstack函数检查栈是否有足够空间。 

 lua_isnumber不会检查值是否为数字类型,而是检查值是否能转换为数字类型。lua_isstring也具有相同的行为。因此,lua_isstring 对于任意数字都返回真。 

 lua_settop(L,0)能清空栈(将栈顶设置到索引0) 

 可以使用负数索引来调用lua_settop,从栈中弹出n个元素, 

 #define lua_pop(L,n) lua_settop(L,-(n)-1) 

 当为lua编写库函数时,只有一种标准的错误处理方法。当一个C函数检测到一个错误时,它就应该调用Lua_error。lua_error函数会清理lua中所有需要清理的东西,然后跳转回发起执行的那个lua_pcall,并附上一条错误消息。 



 lua调用c函数,但并不是任意的c函数,能任意调用c函数的lua扩展包存在不可移植和安全问题。 

 栈不是一个全局性的结构,每个函数都有自己的局部私有栈。当lua调用一个C函数,第一个参数总是局部栈的索引1. 

 static int sinL(lua_State *L) 

 { 

double d = lua_tonumber(L,1);//获取参数 

lua_pushnumber(L,sin(d));//压入结果 

return 1;//结果的数量 
  

 } 

 所有注册到lua中的函数都具有相同的原型: 

 typedef int (*lua_CFunction) (lua_State *L); 

 lua_pushcfunction用来注册C函数,传入一个指向C函数的指针,在lua中创建一个“函数”类型的值,表示对应的C函数, 

 lua_pushcfunction(L,sinL); 

 lua_setglobal(L,"mysin"); //将lua中创建的函数值赋予全局变量mysin。 



 lua通过注册过程记录下C函数,然后使用这些函数的地址直接调用它。 



 如果需要注册多个函数,辅助库中的luaL_register函数可以接收一些C函数及其名称,并将这些函数注册到一个模块同名的table。 

 一,定义模块函数 

 static int sinL(lua_State *L) 

 { 

... 

 } 

 二,声明一个数组元素类型为luaL_Reg结构,该结构包含一个字符串和一个函数指针。 

 static const struct luaL_Reg mylib[] = { 

{"sin",sinL}, 

... 

{NULL,NULL}//结尾 

 } 

 三,声明一个主函数,并在其中调用luaL_register. 

 int luaopen_mylib(lua_State *L){ 

luaL_register(L,"mylib",mylib); 

return 1; 

 } 



 LuaL_openlibs 会打开的标准库列表位于linit.c中。 



 lua_rawseti(L,t,key)等价于: 

 lua_pushnumber(L,key); 

 lua_insert(L,-2);//将key放到前一个值得下面 ps:第一个值就是要set到table中的值。 

 lua_rawset(L,t); 





 C函数从lua中收到一个字符串时,1,不要在访问字符串时从栈中弹出它,2,不要修改字符串。 



 lua中非局部变量可存储在注册表,环境和upvalue中。 

 注册表是一个全局table,只能被C代码访问。 

 注册表总是位于一个“伪索引(Pseudo-Index)”上,这个索引值由LUA_REGISTRYINDEX定义。 

 注册表中不应使用数字类型的key,因为这种key是被“引用系统”所保留的。 



 lua5.1之后,lua中注册的所有C函数有自己的环境table,通过伪索引LUA_EVNIRONINDEX 访问。 

 lua_pushclosure,创建一个新的closure,其第二个参数是一个基础函数,第三个参数是upvalue的数量。在创建一个新的closure前,必须将upvalue的初值压入栈中。 

 lua_upvalueindex可以生成一个upvalue的伪索引。 

 轻量级userdata,轻量级userdata是一种表示C指针的值(即void*)。由于它是一个值,所以不用创建。通过调用lua_pushlightuserdata来实现压栈。 

 轻量级userdata不是缓冲,只是一个指针而已,亦没有元表,轻量级userdata无须受垃圾收集器的管理。轻量级userdata需要用户自己管理内存。 

 在对象原始内存之外的其他资源,当对象成为垃圾被收集后,通过“终结函数(finalizer)”的特殊机制来释放,lua通过元方法__gc来指定终结函数。该原方法只对userdata值有效。 



 lua不支持共享内存的抢先式多线程。 

 lua_State *lua_newstate(lua_Alloc f,void *ud); 

 该函数接收两个参数分配函数和用户数据。通过该函数创建的状态会调用f来完成所有的内存分配和释放。P294 

 垃圾收集器API : lua_gc,collectgarbage函数。