从C调用Lua


如何使用CAPI存取操作Lua中的值,一组能使C与Lua交互的函数


Lua_C数据交互使用一个虚拟栈:luaState


Lua和C的差异:

1、Lua使用垃圾回收,C使用显式的内存释放

 2、Lua使用动态类型,C使用静态类型


lua头文件介绍:
lua.h定义了lua提供的基础函数,包括创建Lua环境(LuaState),调用Lua函数(lua_pcall)...
lauxlib.h定义了辅助库提供的函数,以luaL_开头


构建Lua环境执行Lua代码的简单例子:
<span style="font-size:14px;">#include <stdio.h>
#include <string.h>
extern "C" {  
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
} 




int main(void){
	char buff[256];
	int error;
	lua_State *L = luaL_newstate();		//打开lua
	luaL_openlibs(L);					//打开标准库


	while(fgets(buff,sizeof(buff),stdin)!=NULL){
		error = luaL_loadbuffer(L,buff,strlen(buff),"line") || lua_pcall(L,0,0,0);
		if(error){
			fprintf(stderr,"%s",lua_tostring(L,-1));
			lua_pop(L,1);		//从栈中弹出错误消息
		}
	}
	lua_close(L);
	return 0;
}</span>




使用栈交互:
优点: 除了在c/c++上方便使用还可以轻松应用到其他语言
  如果在C中保存Lua table变量,Lua的垃圾回收无法搜索出这个table不是垃圾文件


在Lua中调用该栈的时候,只会改变栈顶,而使用C可以自由检索中间元素


压入栈元素的CAPI:
lua_pushxxx  :  lua_pushnil(L),lua_pushboolean(L,bool)
压入元素需要提前检查空间:int lua_checkstack(lua_State* L,int sz)


查询栈元素的CAPI:
规则:关于索引->第一个压入栈的元素索引为1;第二个压入索引为2...直到栈顶
还可以以栈顶为参考物:-1表示栈顶元素,-2表示栈顶下面的元素...知道栈底
例子:lua_tostring(L,-1)会将栈顶的值作为一个字符串返回


检查栈中元素的类型:int lua_is*(lua_State* L, int index) : lua_isnumber,lua_istable...
返回栈中元素的类型:lua_type(L,index) : LUA_TNIL,LUA_TBOOLEAN,LUA_TTABLE....
从栈中获取一个值: lua_to*(L,index): lua_toboolean,lua_objlen




其他栈操作:
int lua_gettop(L) :返回栈元素的个数,或者是栈顶的索引
void lua_settop(L,int index) 使用lua_settop(L,0)可以清空栈,用负数索引可以从栈弹出元素,大于len则用栈顶元素填充
void lua_pushvalue(L,index) 将指定索引元素副本压入栈顶
void lua_remove(L,index) 删除指定索引元素,下移填补
void lua_insert(L,index) 上移所有元素开辟一个槽空间
void lua_replace(L,index) :  弹出栈顶的值,设置到指定索引上(原栈顶移除)


例子:
<span style="font-size:14px;">
	lua_State* L = luaL_newstate();


	lua_pushboolean(L,1);
	lua_pushnumber(L,10);
	lua_pushnil(L);
	lua_pushstring(L,"hello");


	stackDump(L);


	lua_pushvalue(L,-4);
	stackDump(L);


	lua_replace(L,3);
	stackDump(L);


	lua_settop(L,6);
	stackDump(L);


	lua_remove(L,-3);
	stackDump(L);


	lua_settop(L,-5);
	stackDump(L);


	lua_close(L);


	getwchar();</span>




CAPI中的错误处理
使用setjmp机制
“无保护”模式:当Lua发生错误时,Lua会调用一个“紧急”函数,然后Lua会结束应用程序
不会抛出异常的函数:luaL_newstate,lua_load,lua_pcall,lua_close
如果内存分配错误,不想结束应用程序的方法:
1、设置一个“紧急”函数不要把控制权返回给Lua
2、代码在“保护模式”下运行(常用)


luaL_loadfile(L,fname): 从fname的文件中加载程序块
lua_getglobal(L,"width") :将对应的全局变量值压入栈中
在栈中对table的操作:
1、lua_gettable(L,index):查找指定table以栈顶为key的value
详细:index是table在相对栈顶的位置,取栈顶元素为key找value,然后将栈顶的key替换为value,这样栈顶就是key对应的value值
lua_getfield(L,-1,key):一个lua_gettable的特化版本,不需要将key压入栈顶


2、lua_settable(L,index)
详细:将key和value一次压入栈,index为table在当前栈的位置,lua_settable压入对应key和value后,弹出key和vlaue
lua_setfield(L,-2,index):lua_settable的特化,value压入栈顶,index为key


3、lua_newtable(L):压入一个空的table


4、lua_pcall(L,pNum,rNum,errNum):调用Lua函数,成功则返回0
pNum:函数的参数个数
rNum:函数的返回值个数
errNum:错误处理函数的索引
发生错误会返回一个非零值,并在栈中压入一条错误信息

int invokeLuaFun(int x,int y){
	lua_State* L = luaL_newstate();
	luaL_openlibs(L);					//打开标准库
	if(luaL_loadfile(L,"config.lua") || lua_pcall(L,0,0,0))
		error(L,"cannot run config.lua:%s",lua_tostring(L,-1));

	lua_getglobal(L,"f");
	lua_pushnumber(L,x);
	lua_pushnumber(L,y);

	if(lua_pcall(L,2,1,0)!=0)
		error(L,"error running function 'f':%s",lua_tostring(L,-1));

	if(!lua_isnumber(L,-1))
		error(L,"function 'f' must return a number");
	int z = lua_tonumber(L,-1);
	lua_pop(L,1);		//弹出栈顶
	return z;

}


------------------------------------------------------------------------
void lua_rawgeti(lua_State *L,int index,int key);
void lua_rawseti(lua_State *L,int index,int key);
void lua_pushnumber(lua_State *L,int key);
void lua_insert(lua_State *L,int index);
void lua_rawget(lua_State *L,int index);
void lua_rawset(lua_State *L,int index);
void luaL_checktype(Lua_State *L,int index, TYPE)  TYPE:LUA_TTABLE,LUA_TFUNCTION
int luaL_checktype(lua_State *L,int index);
void lua_pushvalue(lua_State *L,int index);
void lua_call(lua_State* L,int index,int key);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值