Lua与C的交互
C代码不可以直接与Lua代码交互,中间是通过Lua引擎实现的(C代码要调用Lua需要链上Lua引擎库 gcc lua.c -llua50)
gcc lua.c -llua5.1 //链上Lua50引擎库,之后lua.c就可以 如果提示没有lua50库,就使用 sudo apt-get install liblua5.1-0-dev 安装lua引擎库
Lua堆栈一般最多可以容纳20个参数
第一部分:Lua调用C函数
STEP1 执行lua脚本
lua.c内容如下
#include
#include
#include
int main()
{
//1.创建lua state(Lua解析器实例,类似于java虚拟机) //将来与Lua交互必须使用创建的解析器实例, //每个线程可以创建多个解析器实例
lua_State* luaInst = lua_open()
//2.初始化Lua解析器实例对象
luaL_openlibs(luaInst)
//3.执行Lua
luaL_dofile(luaInst,"1.lua") //执行当前目录下的lua脚本
return 0;
}
当加入main函数,可以实现与系统自带解析器一样的功能
#include
#include
#include
int main(int argc,char*argv[])
{
lua_State* luaInst = lua_open()
luaL_openlibs(luaInst)
luaL_dofile(luaInst,argv[1]) //执行传入参数指定的Lua脚本
return 0;
}
利用gcc lua.c -llua5.1 生成a.out
./a.out 1.lua 与lua 1.lua执行结果一样
---------------------------------------------------------------------------
STEP2 lua调用C函数
lua.c内容如下
#include
#include
#include
//1. 定义接口函数,接口函数有固定的格式,int(*func_type)(lua_State*)
//2.将接口函数注册到lua解析器中
//3.执行lua脚本,在脚本中执行对应的函数
void callbylua()
{
printf("this function is called by lua ");
}
int c1(lua_State* L)
{
callbylua();
return 0;
}
int main()
{
lua_State* luaInst = lua_open();
luaL_openlibs(luaInst,"c1",c1) ; //注册C函数到Lua
luaL_dofile(luaInst,"./1.lua"); //执行传入参数指定的Lua脚本
return 0;
}
1.lua内容如下
print("this is 1.lua")
c1()
---------------------------------------------------------------------------
STEP3 lua调用C函数:带有参数
lua.c内容如下
#include
#include
#include
void cprint(int a,int b,char* c)
{
printf("%d,%d,%s\n",a,b,c);
}
int c2(lua_State* L) //需要从lua栈中获取三个参数
{
int a = lua_tonumber(L,1); //根据lua解析器栈的索引值来获取参数
int b = lua_tonumber(L,2);
char* c = lua_tostring(L,3);
cprint(a,b,c);
return 0;
}
int main()
{
lua_State* luaInst = lua_open();
luaL_openLibs(luainst);
lua_register(luaInst,"cprint",c2);
luaL_dofile(luaInst,"./1.lua");
}
1.lua内容如下
print("this is 1.lua")
c2(10,20,“helloC”) //lua解析器中有一个栈, 栈中的元素从左往右,依次是栈底,到栈顶;索引栈分为 索引与 尾索引(负数)
---------------------------------------------------------------------------
STEP4 lua调用C函数:带有参数和返回值
lua.c内容如下
#include
#include
#include
int cadd(int x,int y)
{
return x+y;
}
int c4(lua_State* L)
{
int x = lua_tonumber(L,1);
int y = lua_tonumber(L,2);
int s = cadd(x,y);
lua_pushnumber(L,s); //返回值
return 1; //返回有多少个返回值
}
int main()
{
lua_State* luaInst = lua_open();
luaL_openLibs(luainst);
lua_register(luaInst,"cadd",c4)
luaL_dofile(luaInst,"./1.lua")
}
1.lua内容如下
print("this is 1.lua")
ret = cadd(10,20) //lua解析器中有一个栈, 栈中的元素从左往右,依次是栈底,到栈顶;索引栈分为 索引与 尾索引(负数)
print("cadd ret =",ret)
---------------------------------------------------------------------------
STEP5 lua调用C函数:带有参数和返回值
lua.c内容如下
#include
#include
#include
void cswap(int* x,int* y)
{
return x+y;
}
int c5(lua_State* L)
{
int x = lua_tonumber(L,1);
int y = lua_tonumber(L,2);
cswap(x,y);
lua_pushnumber(L,x); //返回值
lua_pushnumber(L,y); //返回值
return 2; //返回有多少个返回值
}
int main()
{
lua_State* luaInst = lua_open();
luaL_openLibs(luainst);
lua_register(luaInst,"cswap",c5)
luaL_dofile(luaInst,"./1.lua")
}
1.lua内容如下
print("this is 1.lua")
a,b = cswap(10,20) //lua解析器中有一个栈, 栈中的元素从左往右,依次是栈底,到栈顶;索引栈分为 索引与 尾索引(负数)
print("cadd ret =",a,b)
第二部分:C调用Lua函数
#include
#include
#include
// 1. 调用一个没有参数,没有返回值的函数
// call lua function: foo
int main1(int argc, char* argv[])
{
// 创建一个Lua解析器环境实例,类似Java的虚拟机
lua_State* luaInst = lua_open();
// 初始化Lua解析器环境实例对象
luaL_openlibs(luaInst);
// 执行Lua
luaL_dofile(luaInst, "2.lua");
// 在调用lua_call函数去调用lua函数之前,需要把lua的函数放入栈(foo是一个Lua中的函数变量)
lua_getglobal(luaInst, "foo");
// 调用lua的一个函数,有没有指定哪个函数???? 第二个参数是所调用函数的参数个数,第三个参数是返回值的个数
lua_call(luaInst, 0, 0); //没有指定具体的函数,解析器的栈决定 ;该函数调用完毕之后,解析器栈内部会清空
return 0;
}
----2.lua的内容
function foo()
print("foo in lua is called")
end
// 2. 调用一个有参数的函数
int main2(int argc, char* argv[])
{
// 创建一个Lua解析器环境实例,类似Java的虚拟机
lua_State* luaInst = lua_open();
// 初始化Lua解析器环境实例对象
luaL_openlibs(luaInst);
// 执行Lua
luaL_dofile(luaInst, "2.lua");
// 在调用lua_call函数去调用lua函数之前,需要把lua的函数放入栈
lua_getglobal(luaInst, "luaprint"); // foo其实是一个函数类型变量
lua_pushnumber(luaInst, 100);
lua_pushstring(luaInst, "hello");
// 调用lua的foo函数,有没有指定哪个函数????
lua_call(luaInst, 2, 0);
return 0;
}
----2.lua的内容
function luaprint(x, y)
print("lua get arg:", x, y)
end
// 3. 调用一个有返回值的函数
int main(int argc, char* argv[])
{
// 创建一个Lua解析器环境实例,类似Java的虚拟机
lua_State* luaInst = lua_open();
// 初始化Lua解析器环境实例对象
luaL_openlibs(luaInst);
// 执行Lua
luaL_dofile(luaInst, "2.lua");
// 在调用lua_call函数去调用lua函数之前,需要把lua的函数放入栈
lua_getglobal(luaInst, "luaadd"); // foo其实是一个函数类型变量
lua_pushnumber(luaInst, 100);
lua_pushnumber(luaInst, 200);
// 调用lua的foo函数,有没有指定哪个函数????
lua_call(luaInst, 2, 1);
int result = lua_tonumber(luaInst, -1);
printf("luaadd result is %d\n", result);
lua_pop(luaInst, 1); // POP 一个元素,保证栈被清空
return 0;
}
----3.lua的内容
function luaadd(x, t)
return x+y;
end
第三部分:Lua与C/C++纯数据交互
原理:Lua解析器实际是将Lua脚本中的语句翻译为C代码保存在Lua解析器中,因而可以使用C直接编辑Lua解析器中的数据结构
lua.c内容如下:
//向lua解析器中写入变量a并赋值
#include
#include
#include
// 放一个普通的全局变量
int main1(int argc, char* argv[])
{
// 创建一个Lua解析器环境实例,类似Java的虚拟机
lua_State* luaInst = lua_open();
// 初始化Lua解析器环境实例对象
luaL_openlibs(luaInst);
// push一个value到栈
lua_pushnumber(luaInst, 100); //为lua_setglobal做铺垫,因为此时栈为空
// 放一个a变量
lua_setglobal(luaInst, "a"); //lua_setglobal函数执行过程为:从栈顶获取一个值赋值给“a”,然后将栈顶元素弹出来;将a压入堆栈
// 执行Lua
luaL_dofile(luaInst, "3.lua");
return 0;
}
//3.lua中的内容为
print(a) //虽然3.lua没有a变量,但是C语言已经将a加入了栈中
// 放一个表
int main2(int argc, char* argv[])
{
// 创建一个Lua解析器环境实例,类似Java的虚拟机
lua_State* luaInst = lua_open();
// 初始化Lua解析器环境实例对象
luaL_openlibs(luaInst);
// 阶段1:先创建全局表b
// push一个value到栈
lua_newtable(luaInst);
// 放一个b变量
lua_setglobal(luaInst, "b");
// 阶段2:给b来一个成员,叫name
lua_getglobal(luaInst, "b"); // 将b表,放入栈 |__________|
lua_pushstring(luaInst, "tom"); |__________|目前栈顶是“tom” -1位置 key是"name" value是"tom"
lua_setfield(luaInst, -2, "name"); // b.name = "tom" |__________|栈顶下面有一个table -2位置
|__________|
// 执行Lua
luaL_dofile(luaInst, "3.lua");
return 0;
}
int main3()
{
// 创建一个Lua解析器环境实例,类似Java的虚拟机
lua_State* luaInst = lua_open();
// 初始化Lua解析器环境实例对象
luaL_openlibs(luaInst);
//这类函数需要考虑栈的具体状态,需要查看各个函数弹栈与否,画图分析
lua_newtable(luaInst);
lua_pushstring(luaInst, "tom");
lua_setfield(luaInst, -2, "name");
lua_setglobal(luaInst, "b"); //简化/优化上面的代码,setfield会弹出tom的值,但是表还在
luaL_dofile(luaInst, "3.lua");
}
int main()
{
lua_State* luaInst = lua_open();
luaL_openlibs(luaInst);
lua_newtable(luaInst);
lua_pushnumber(luaInst, 1);
lua_pushstring(luaInst, "hello lua");
lua_settable(luaInst, 1); //相当于t[k] = v 操作 ,(由于setfield下标是字符串,settable下标是数字)
lua_setglobal(luaInst, "b");
luaL_dofile(luaInst, "3.lua");
}
3.lua内容如下:
print(a)
print(b.name)
print(b[1])