lua和c/c++交互

lua虚拟栈

lua 和c采用虚拟栈的方式传递数据,栈中的元素是以lua 数据结构的方式存储,c/c++可以从该栈压入数据或者去除数据,通过这种方式实现数据传输,lua中的值由lua来管理,c/c++的值lua不关心,比如c/c++需要一个变量table或者string等,其调用lua提供的接口,由lua产生并且进行内存管理,需要注意的是这里的栈是lua_State的数据栈,其还有调用栈,和Global_State

另外虚拟栈的索引,分为正数索引和负数索引:正数索引是从栈底开始计数,而负数索引是从栈顶开始计数lua和c/c++交互_第1张图片

栈操作api

关于栈的操作
lua_State * luaL_newstate(void);
创建一个新的Lua状态。返回新状态,或者NULL是否存在内存分配错误。
void lua_close(lua_State * L);
销毁lua状态中的所有对象并释放此状态使用的所有动态内存
弹出n个堆栈中的元素 void lua_pop(lua_State * L,int n);
返回堆栈中顶部元素的索引 int lua_gettop(lua_State * L);

C操作栈内数据
常用的入栈函数 lua_push*(lua_State * L, value );
常用的读取栈内内容函数lua_to*(lua_State *L, int index)
判断栈内内容函数 lua_is * (lua_State *L, int index), 如果index所指向的值为给定类型则返回1,否则返回

对于lua中的值
int lua_getglobal(lua_State * L,const char * name);将全局值推入堆栈,name为改值的name
void lua_setglobal(lua_State * L,const char * name);从堆栈中弹出一个值并将其设置为全局的新值

在堆栈中建立数据并且建立关系
void lua_newtable(lua_State * L);创建一个新的空表并将其推入堆栈
int lua_getfield(lua_State * L,int index,const char * k);将t[k]值推送到堆栈,其中t是给定索引处的值, 如在索引2处有一个table,则函数执行结果为将table 中key为k元素的值添加到堆栈
void lua_setfield(lua_State * L,int index,const char * k);是等价于t[k] = v,其中t是给定索引处的值,v是堆栈顶部的值。

使用自定义数据类型
void * lua_newuserdata(lua_State * L,size_t size);
此函数分配具有给定大小的新内存块,将具有块地址的新完整用户数据推入堆栈,并返回此地址。主程序可以自由使用这个内存。

关于函数调用
int lua_pcall(lua_State * L,int nargs,int nresults,int msgh);
在保护模式下调用函数。其中nargs表示参数数目,nresults表示返回值个数,msgh为错误处理函数索引
在调用lua 函数时,首先将函数入栈然后将参数压入栈,其中第一个参数第一个压入,最后函数执行完成后,将返回结果压入栈内

C/C++中加载lua脚本
int luaL_dofile(lua_State * L,const char * filename);加载并运行给定的文件返回false表示失败

lua_State * lua_newthread(lua_State * L);
创建一个新线程,将其推送到堆栈上,并返回一个指向lua_State该新线程的指针。此函数返回的新线程与原始线程共享其全局环境,但具有独立的执行堆栈。没有显式函数来关闭或销毁线程。与任何Lua对象一样,线程可以进行垃圾收集。

C/C++调用lua

C/C++调用lua需要首先创建虚拟栈,然后加载lua脚本并运行,之后根据业务需求通过虚拟栈和lua 交互

lua调用C/C++

第一种方法就是直接将函数写入lua.c中,然后重新编译lua
函数要遵循规范(可在lua.h中查看):typedef int (*lua_CFunction) (lua_State *L);

第二种方法是使用静态依赖的方式
我们在c++中写一个模块函数,将函数注册到lua解释器中,然后由c++去执行我们的lua文件,然后在lua中调用刚刚注册的函数

第三种是使用dll动态链接的方式
我们通过编写C/C++模块,之后lua直接调用require加载该模块,像调用lua模块一样
需要注意的是,该C/C++模块需要一个luaopen_xxx导出函数,其需要交互的函数,需要通过struct luaL_Reg进行添加,其方式是key,value的方式添加,并且以NULL, NULL结尾,如

static const struct luaL_Reg myLib[] = 
{
	{"average", averageFunc},  //averageFunc为函数名
	{"sayHello", sayHelloFunc},
	{NULL, NULL}       //数组中最后一对必须是{NULL, NULL},用来表示结束    
};

之后在luaopen_xxx函数中需要进行注册通过luaL_newlib函数(void luaL_newlib(lua_State * L,const luaL_Reg l []))
另外所有的函数需要遵循规范:typedef int (*lua_CFunction) (lua_State *L);
之后将模块编译成动态库。

你可能感兴趣的:(lua)