Luasocket和lua CAPI


lua安装

Lua在ubuntu上安装非常简单,但是需要一个readline的头文件。


apt-get install libreadline6-dev libncurses-dev


然后进入lua目录
make linux
make linux install


luasocket

在看lunatest的时候,其中使用luasocket库,这个库实现了基本的socket功能。
基本看了一下luasocket的实现,觉得主要是使用luaL_tostring函数,从栈中获得lua的string,然后调用socket.send函数进行发送。


receive的时候,调用socket.receive获得data后,通过pushlstring,压入栈,传递给lua。


debug

debug 库由两种函数组成:自省(introspective)函数和 hooks。
自省函数使得我们可以检查运行程序的某些方面,比如活动函数栈、当前执行代码的行号、本地变量的名和值。
Hooks 可以跟踪程序的执行情况。


Debug 库中的一个重要的思想是栈级别(stack level)。
一个栈级别就是一个指向在当前时刻正在活动的特殊函数的数字,也就是说,这个函数正在被调用但还没有返回。
调用 debug 库的函数级别为 1,调用他(他指调用 debug 库的函数)的函数级别为 2,以此类推。


debug.getinfo

debug.getinfo(foo),将返回关于这个函数信息的一个表。
这个表有下列一些域:
source,标明函数被定义的地方。
short_src,source 的简短版本(最多 60 个字符),记录一些有用的错误信息。
linedefined,source 中函数被定义之处的行号。
what,标明函数类型。如果 foo 是一个普通得 Lua 函数,结果为 “Lua”;
如果是一个 C 函数,结果为 “C”;
如果是一个 Lua 的主 chunk,结果为 “main”。
name,函数的合理名称。
namewhat,上一个字段代表的含义。
nups,函数的 upvalues 的个数。
func,函数本身;详细情况看后面。
以数字 n 调用 debug.getinfo(n)时,返回在 n 级栈的活动函数的信息数据。
currentline,即在那个时刻函数所在的行号。


hook

debug 库的 hook 是这样一种机制:
注册一个函数,用来在程序运行中某一事件到达时被调用。


有四种可以触发一个 hook 的事件:
Lua 调用一个函数的时候 call 事件发生;
当每次函数返回的时候,return 事件发生;
Lua 开始执行代码的新行时候,line 事件发生;
运行指定数目的指令之后,count 事件发生。
Lua 使用单个参数调用 hooks,参数为一个描述产生调用的事件:”call”、”return”、”line” 或 “count”。
另外,对于 line 事件,还可以传递第二个参数:新行号。
我们在一个 hook 内总是可以使用 debug.getinfo 获取更多的信息。
为了监控 call、return 和 line 事件,可以将他们的第一个字母(‘c’、’r’ 或 ‘l’)组合成一个 mask 字符串即可。
要想关掉 hooks,只需要不带参数地调用 sethook 即可。


CAPI

Lua API 没有定义任何类似 lua_Value 的类型。
替代的方案,它用一个抽象的栈在 Lua 与 C 之间交换值。
Lua 以一个严格的 LIFO 规则(后进先出;也就是说,始终存取栈顶)来操作栈。
当你调用 Lua 时,它只会改变栈顶部分。
你的C代码却有更多的自由;更明确的来讲,你可以查询栈上的任何元素,甚至是在任何一个位置插入和删除元素。


Lua 要么做一份内部的拷贝要么重新利用已经存在的字符串。因此,一旦这些函数返回之后你可以自由的修改或是释放你的缓冲区。
Lua_tostring 函数返回一个指向字符串的内部拷贝的指针。你不能修改它(使你想起那里有一个 const)。
只要这个指针对应的值还在栈内,Lua 会保证这个指针一直有效。
当一个 C 函数返回后,Lua 会清理他的栈,
所以,有一个原则:永远不要将指向 Lua 字符串的指针保存到访问他们的外部函数中。


调用c函数

从 Lua调用 C 函数我们必须注册函数,也就是说,我们必须把 C 函数的地址以一个适当的方式
传递给 Lua 解释器。
任何在 Lua 中注册的函数必须有同样的原型,这个原型声明定义就是 lua.h 中的


lua_CFunction:
    typedef int (*lua_CFunction) (lua_State *L);
Lua 的 C 库就是这样实现的。除了定义 C 函数之外,还必须定义一个特殊的用来和 Lua 库的主 chunk 通信的特殊函数。
一旦调用,这个函数就会注册库中所有的 C 函数,并将他们保存到适当的位置。


luaL_openlib 函数接受一个 C 函数的列表和他们对应的函数名,并且作为一个库在一个 table 中注册所有这些函数。
第二步,我们声明一个数组,保存所有的函数和他们对应的名字。
这个数组的元素类型为 luaL_reg:是一个带有两个域的结构体,一个字符串和一个函数指针。
第三步,我们使用 luaL_openlib 声明主函数。
最后在lua中调用loadlib


一个 userdatum 提供了一个在 Lua 中没有预定义操作的 raw 内存区域。
一个 light userdatum 是一个表示 C 指针的值,使用 light userdata 你必须自己管理内存,因为他们和垃圾收集器无关。


Lua_stack

正数代表栈中的绝对位置(从栈底开始),负数代表从栈顶的相对位置。
对于栈的大小是要c程序来进行维护的,使用lua_checkstack to grow the stack size,每次调用此函数,
保证有LUA_MINSTACK空间有效。


module(name,…)
其他参数是作为函数一次应用于module。
require()
packet.preload
package.path
package.cpath 加载c库时,搜索路径
加载库后Then it tries to find a C function inside the library to be used as the loader.
The name of this C function is the string “luaopen_” concatenated with a copy of the module name
where each dot is replaced by an underscore。(.变为_)。
package.seeall
把module的metatable的__index设置为全局变量,这样模块就继承了全局变量。



All functions from the auxiliary library are defined in header file lauxlib.h and have a prefix luaL_.


All functions in the auxiliary library are built on top of the basic API,
and so they provide nothing that cannot be done with this API.


Several functions in the auxiliary library are used to check C function arguments.
Their names are always luaL_check* or luaL_opt*.
All of these functions throw an error if the check is not satisfied.
Because the error message is formatted for arguments (e.g., “bad argument #1”),
you should not use these functions for other stack values.


lua_settable(l,index)
从栈中弹出key 和val进行设置给index。


参考资料

http://lua-users.org/wiki/ 有一个lua的在线教程,值得一看
http://www.lua.org/
http://www.lua.org/pil/ Programming in Lua (first edition) 在线版
http://www.lua.org/manual/5.1/ LUA5.1手册
http://lua-users.org/wiki/UnitTesting 介绍几种lua测试框架
http://www.nessie.de/mroth/lunit/ lunit用于lua的测试框架,类似Cunit


lua中文教程.pdf 必看


lua5..1语法速查手册