不管lua与c交互还是c与lua交互,实现的原理都是通过虚拟栈来实现的,当lua调用C语言里面的一个变量,首先C语言需要将一个值压入堆栈,然后设置到global中去,从栈顶弹出一个值,并将这个值起一个名字:
一:lua调用C
int width = 100;
// lua访问c中的变量width 将改数字压入堆栈
lua_pushnumber(L, width);
// 从栈顶弹出一个值并将其值的名字命名为width
lua_setglobal(L, "width");
定义一个C函数:供lua调用
/**
lua调用c函数
返回值:lua调用该C函数 返回值的数量
*/
int luaCallCFunc(lua_State* L) {
int width = 100;
// 压入堆栈
lua_pushnumber(L, width);
lua_pushstring(L, "test");
// 该函数对lua返回两个值
return 2;
}
// lua调用c函数
lua_pushcfunction(L, luaCallCFunc);
lua_setglobal(L, "luaCallCFunc");
lua程序结果:
print('width is ' .. width);
local a, b = luaCallCFunc();
print("res is " .. a);
print("b is " .. b);
二:C调用lua
if.lua:
name = "bob";
age = 20;
mystr = "hello lua"
mytable = { name = "tom", id = 123456 };
function add(x, y)
return 2 * x + y;
end
test = 1;
print("test is " .. test);
print('width is ' .. width);
local a, b = luaCallCFunc();
print("res is " .. a);
print("b is " .. b);
main.c:
lua虚拟栈是从顶部索引-1开始往下递减,想取到栈顶的元素只需要lua_to数据类型(lua_State* L,int -1)即可。c调用lua函数的方式是:lua_pcall(lua_State* L,int nargs,int nresults,int msgn)
c调用lua add方法 第二个参数表示lua函数需要几个参数,第三个参数表示lua函数返回几个值,0是否需要错误处理
int retLoad = luaL_loadfile(L, "/Users/hi/study/js_study/luas/if.lua");
if(retLoad == 0) {
printf("load file success retLoad:%d\n",retLoad);
}
if(retLoad || lua_pcall(L, 0, 0, 0)) {
return -1;
}
// lua获取全局变量并将变量name的值并且返回栈顶
lua_getglobal(L, "name");
lua_getglobal(L, "age");
int age = lua_tointeger(L, -1);
const char* name = lua_tostring(L, -2);
printf("name is %s\n",name);
printf("age is %d\n",age);
lua_getglobal(L, "add");
lua_pushnumber(L, 10);
lua_pushnumber(L, 20);
for(int i = 1; i < 3; i++) {
printf("number:%f\n",lua_tonumber(L, -i));
}
// c调用lua add方法 第二个参数表示lua函数需要几个参数,第三个参数表示lua函数返回几个值,0是否需要错误处理
int pcallRet = lua_pcall(L,2,1,0);
if(pcallRet != 0) {
return -1;
}
int val = lua_tonumber(L, -1);
printf("val is %d\n",val);
// 弹出栈顶
lua_pop(L, -1);
// 再次查看栈什么都没有了,因为lua在返回函数计算结果的时候会清空栈,只保留返回值
for (int i = 1; i < 3; i++) {
printf("number %f\n",lua_tonumber(L, -i));
}