lua的c api 总结

lua和c的交互入门例子,功能是把字符串中的key=value字符串全部转换成XML格式<key>value</key>
代码如下:
使用lua的string.gsub 函数转换字符串(作为例子):
int main()
{
	//Lua示例代码
	char *szLua_code =
	   "r = string.gsub(c_Str, c_Mode, c_Tag) --宿主给的变量 "
	   "u = string.upper(r)";
	//Lua的字符串模式
	char *szMode = "(%w+)%s*=%s*(%w+)";
	//要处理的字符串
	char *szStr = "key1 = value1 key2 = value2";
	//目标字符串模式
	char *szTag = "<%1>%2</%1>";
	
	lua_State *L = luaL_newstate();
	luaL_openlibs(L);
	
	//把3个变量(c_Str, c_Mode, c_Tag)发送到Lua虚拟机
	lua_pushstring(L, szMode);//把C字符串压入栈顶
	lua_setglobal(L, "c_Mode");//lua_setglobal的作用是把栈顶的数据传到Lua环境中作为全局变量
	lua_pushstring(L, szTag);
	lua_setglobal(L, "c_Tag");
	lua_pushstring(L, szStr);
	lua_setglobal(L, "c_Str");
	
	//执行
	bool err = luaL_loadbuffer(L, szLua_code, strlen(szLua_code),
	           "demo") || lua_pcall(L, 0, 0, 0);
	if(err)
	{
	   //如果错误,显示
	   cerr << lua_tostring(L, -1);
	   //弹出栈顶的这个错误信息
	   lua_pop(L, 1);
	}
	else
	{
	   //Lua执行后取得全局变量的值
	   lua_getglobal(L, "r");//从Lua环境中取得全局变量压入栈顶
	   cout << "r = " << lua_tostring(L,-1) << endl;//把栈顶的数据转成字符串
	   lua_pop(L, 1);//调用前与调用后栈里的数据量不变
	   lua_getglobal(L, "u");
	   cout << "u = " << lua_tostring(L,-1) << endl;    
	   lua_pop(L, 1);
	}
	lua_close(L);
	return 0;
}



C++和Lua之间交互接口一直是依赖着栈。Lua C API就是用于操作栈的,操作列举如下:



1、虚拟机维护

lua_State *lua_newstate (lua_Alloc f, void *ud);
创建的一个新的独立的状态机。如果创建不了(因为内存问题)返回 NULL 。参数 f 是一个分配器函数; Lua 将通过这个函数做状态机内所有的内存分配操作。第二个参数 ud ,这个指针将在每次调用分配器时被直接传入。 

________________________________________
void lua_close (lua_State *L);
销毁指定 Lua 状态机中的所有对象(如果有垃圾收集相关的元方法的话,会调用它们),并且释放状态机中使用的所有动态内存。在一些平台上,你可以不必调用这个函数,因为当宿主程序结束的时候,所有的资源就自然被释放掉了。另一方面,长期运行的程序,比如一个后台程序或是一个 web 服务器,当不再需要它们的时候就应该释放掉相关状态机。这样可以避免状态机扩张的过大。 

________________________________________
lua_Alloc lua_getallocf (lua_State *L, void **ud);
返回给定状态机的内存分配器函数。如果 ud 不是 NULL ,Lua 把调用 lua_newstate 时传入的那个指针放入 *ud 。 
 

________________________________________
lua_setallocf
void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);
把指定状态机的分配器函数换成带上指针 ud 的 f 。 

2、存取lua全局变量

void lua_setglobal (lua_State *L, const char *name);
作用是把栈顶的数据传到Lua环境中作为全局变量name 
由一个宏定义出来:
#define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, s)


void lua_getglobal (lua_State *L, const char *name);
把lua全局变量 name 里的值压入堆栈。 这个是用一个宏定义出来的:

#define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, s)


3、压入元素到栈里

void lua_pushboolean (lua_State *L, int b);
把 b 作为一个 boolean 值压入堆栈。 
________________________________________
void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n);
把一个新的 C closure 压入堆栈。 
当创建了一个 C 函数后,你可以给它关联一些值,这样就是在创建一个 C closure (参见 §3.4);接下来无论函数何时被调用,这些值都可以被这个函数访问到。为了将一些值关联到一个 C 函数上,首先这些值需要先被压入堆栈(如果有多个值,第一个先压)。接下来调用 lua_pushcclosure 来创建出 closure 并把这个 C 函数压到堆栈上。参数 n 告之函数有多少个值需要关联到函数上。 lua_pushcclosure 也会把这些值从栈上弹出。 
________________________________________
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)
________________________________________
const char *lua_pushfstring (lua_State *L, const char *fmt, ...);
把一个格式化过的字符串压入堆栈,然后返回这个字符串的指针。它和 C 函数 sprintf 比较像,不过有一些重要的区别: 
*        摸你需要为结果分配空间:其结果是一个 Lua 字符串,由 Lua 来关心其内存分配(同时通过垃圾收集来释放内存)。 
*        这个转换非常的受限。不支持 flag ,宽度,或是指定精度。它只支持下面这些: '%%' (插入一个 '%'), '%s' (插入一个带零终止符的字符串,没有长度限制), '%f' (插入一个 lua_Number), '%p' (插入一个指针或是一个十六进制数), '%d' (插入一个 int), '%c' (把一个 int 作为一个字符插入)。 
________________________________________
void lua_pushinteger (lua_State *L, lua_Integer n);
把 n 作为一个整形数压栈。 
________________________________________
void lua_pushlightuserdata (lua_State *L, void *p);
把一个 light userdata 压栈。 
userdata 在 Lua 中表示一个 C 值。 light userdata 表示一个指针。它是一个像数字一样的值:你不需要专门创建它,它也没有独立的 metatable ,而且也不会被收集(因为从来不需要创建)。只要表示的 C 地址相同,两个 light userdata 就相等。 
________________________________________
void lua_pushlstring (lua_State *L, const char *s, size_t len);
把指针 s 指向的长度为 len 的字符串压栈。 Lua 对这个字符串做一次内存拷贝(或是复用一个拷贝),因此 s 处的内存在函数返回后,可以释放掉或是重用于其它用途。字符串内可以保存有零字符。 
________________________________________
void lua_pushnil (lua_State *L);
把一个 nil 压栈。 
________________________________________
void lua_pushnumber (lua_State *L, lua_Number n);
把一个浮点数 n 压栈。 
________________________________________
void lua_pushstring (lua_State *L, const char *s);
把指针 s 指向的以零结尾的字符串压栈。 Lua 对这个字符串做一次内存拷贝(或是复用一个拷贝),因此 s 处的内存在函数返回后,可以释放掉或是重用于其它用途。字符串中不能包含有零字符;第一个碰到的零字符会认为是字符串的结束。 
________________________________________
int lua_pushthread (lua_State *L);
把 L 中提供的线程压栈。如果这个线程是当前状态机的主线程的话,返回 1 。 
________________________________________
void lua_pushvalue (lua_State *L, int index);
把堆栈上给定有效处索引处的元素作一个拷贝压栈。 
________________________________________
const char *lua_pushvfstring (lua_State *L,
                              const char *fmt,
                              va_list argp);
等价于 lua_pushfstring,不过是用 va_list 接收参数,而不是用可变数量的实际参数。 
________________________________________

void *lua_newuserdata (lua_State *L, size_t size)

创建C值到栈

该函数分配一块由size指定大小的内存块, 并放在栈顶
返回值是新分配的块的地址
栈+1, 栈顶是userdata

userdata用来在lua中表示c中的值. 一个完整的userdata有自己的元表, 在垃圾回收时, 可以调用它的元表的__gc方法

________________________________________

void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n)

向栈上压一个C闭包

注册c函数到lua中, 其实没有这回事, lua中只有c闭包
当一个c函数被创建时, 可以绑定几个值在它上面, 从而形成一个闭包.  在任何时刻调用这个c函数时, 都可以访问这几个绑定值. 
绑定的方法: 先一次压入要绑定的n个值到栈上, 然后调用lua_pushcclosure(L, fn, n)这样就形成的一个c闭包
无返回值
栈 –(n - 1) , 一共弹出n个元素(及那些绑定的值), 压入一个cclosure
#define lua_pushcfunction(L, f) lua_pushcclosure(L, f, 0)
#define lua_register(L, n, f) (lua_pushcfunction(L, f), lua_setglobal(L, n))
没有返回值
栈不变化

这个是比较常用的, 以n为lua中的key压入一个0个绑定值的cclosure.

________________________________________

int lua_load (lua_State *L,
              lua_Reader reader,
              void *data,
              const char *chunkname);
加载一个 Lua chunk 。如果没有错误, lua_load 把一个编译好的 chunk 作为一个 Lua 函数压入堆栈。否则,压入出错信息。 lua_load 的返回值可以是: 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值