一、Lua与C之间的交互
1.1 C读写lua全局变量、调用lua函数
代码:
test.lua:
testValue = 10
function add(x, y)
return x + y + testValue
end
test.c:
#include <stdio.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
//调用lua代码中的函数
int lua_add(lua_State *L)
{
lua_getglobal(L, "add"); //获取add函数
lua_pushnumber(L, 100); //向栈中压入第1个参数
lua_pushnumber(L, 200); //向栈中压入第2个参数
if (lua_pcall(L, 2, 1, 0) != 0) //调用lua中的add函数,2个参数,1个返回值
error(L, "call lua add fail: %s", lua_tostring(L, -1));
if (!lua_isnumber(L, -1))
error(L, "function add must return a number.");
int num = lua_tonumber(L, -1); //获取栈顶元素
lua_pop(L, 1); //栈顶元素出栈
return num;
}
//读lua代码中的全局变量
int lua_get_global(lua_State *L)
{
lua_getglobal(L, "testValue"); //获取lua中的全局变量testValue,并压入到栈顶
if (!lua_isnumber(L, -1))
error(L, "function add must return a number.");
int num = lua_tonumber(L, -1); //获取栈顶元素
return num;
}
//写lua代码中的全局变量
void lua_set_global(lua_State *L)
{
lua_pushnumber(L, 20); //把值20压入栈顶
lua_setglobal(L, "testValue"); //lua从栈顶获取值,设置到全局变量testValue中
}
int main()
{
lua_State *L = luaL_newstate();
luaL_openlibs(L);
luaL_dofile(L, "test.lua"); //加载并运行test.lua文件中的代码
printf("lua add1:%d\n", lua_add(L));
printf("lua testValue1:%d\n", lua_get_global(L));
lua_set_global(L);
printf("lua testValue2:%d\n", lua_get_global(L));
printf("lua add2:%d\n", lua_add(L));
lua_close(L);
return 0;
}
编译:
gcc test.c -o test -I/usr/local/include/luajit-2.0 -llua-5.1
运行结果:
[root@bogon 09]# ./test
lua add1:310
lua testValue1:10
lua testValue2:20
lua add2:320
1.2 lua调用C函数
1.2.1 C函数作为应用程序的一部分
代码:
test.c
#include "lualib.h"
static int c_add(lua_State *L)
{
//检查传入的参数是否合法,1表示第1个参数,2表示第2个参数
int op1 = luaL_checknumber(L, 1);
int op2 = luaL_checknumber(L, 2);
int sum = op1 + op2; //C代码中的运算
lua_pushnumber(L, sum); //将结果压入栈中,表示返回值
return 1; //返回值数量,即压入栈中的返回值个数
}
//字符串作为lua代码
const char* testfunc = "print(add(100, 20))";
int main()
{
lua_State *L = luaL_newstate();
luaL_openlibs(L);
//将C函数c_add注册为lua的全局函数add
//lua_register(L, "add", c_add); //方式1
lua_pushcfunction(L, c_add); //方式2
lua_setglobal(L, "add");
if (luaL_dostring(L, testfunc))
printf("failed to invoke.\n");
lua_close(L);
return 0;
}
编译:
gcc test.c -o test -I/usr/local/include/luajit-2.0 -llua-5.1
运行结果:
[root@bogon lua-call-c]# ./test
120
1.2.2 C函数库成为lua的模块
代码:
test.lua
--package.cpath = "./?.so"
local f = require "mytestlib"
print(f.add(20, 10))
print(f.sub(20, 10))
test.c
#include <stdio.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
static int c_add(lua_State *L)
{
//检查传入的参数是否合法,1表示第1个参数,2表示第2个参数
int op1 = luaL_checknumber(L, 1);
int op2 = luaL_checknumber(L, 2);
int sum = op1 + op2; //C代码中的运算
lua_pushnumber(L, sum); //将结果压入栈中,表示返回值
return 1; //返回值数量,即压入栈中的返回值个数
}
static int c_sub(lua_State *L)
{
int op1 = luaL_checknumber(L, 1);
int op2 = luaL_checknumber(L, 2);
int sum = op1 - op2;
lua_pushnumber(L, sum);
return 1;
}
static const struct luaL_Reg mylib[] = {
{"add", c_add},
{"sub", c_sub},
{NULL, NULL}
};
//根据mytestlib,创建一个table;
//并用数组mylib中的信息填充这个table;
//通过luaL_register注册,将这个table保留到栈中。
int luaopen_mytestlib(lua_State *L)
{
luaL_register(L, "mytestlib", mylib);
return 1;
}
编译生成动态库mytestlib.so:
gcc test.c -o mytestlib.o -c -fPIC -I/usr/local/include/luajit-2.0 -llua-5.1
gcc mytestlib.o -shared -o mytestlib.so
运行结果:
[root@bogon 2]# lua test.lua
30
10