lua调用c(lua c api 5.3版本)
2018-03-07 本文已影响14人
90d81be3ec65
一、附上手册,供读者查阅
- lua5.3官方手册:http://www.lua.org/manual/5.3/
- lua5.3中文手册(偶像云风大神翻译):http://cloudwu.github.io/lua53doc/
二、预备知识
- lua搜索路径: package.path, package.cpath
- require规则: 举个例子,require “a.b” 或者require "a/b" 优先搜索目录package.path下的lua文件。假如未搜索到,那么搜索package.cpath中的.so文件,调用luaopen_a_b函数;
- .so: 全称sharedobject(共享动态链接库),类似于windows下的dll文件,供lua调用;
- luaL_len, luaL_newlib 为lua5.3版本api,lua_objlen、luaL_register为lua5.1版本api;
三、代码如下
1、test.c附详细注释
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
static int lua_add(lua_State *L) {
int a = lua_tonumber(L, 1); //lua_tonumber:取浮点数 lua_tointeger: 取整形数
int b = lua_tonumber(L, 2);
lua_pushinteger(L, a + b); //将和压栈,返回给lua
return 1; //1表示一个返回值(a + b)
}
static int lua_table_incrbyone(lua_State *L) {
int len = luaL_len(L, 1);
int a[len];
for (int i = 0; i < len; ++i) {
/*
-1表示栈顶;
取栈顶table中索引为i+1位置的值并压栈;
区别于下述lua_getfield,一个数组一个键值对;
这里也可以这样写,lua_rawgeti(L, 1, i + 1),栈内只有一个元素时候-1(自上往下数)位置和1(自下往上数)位置元素相同;
*/
lua_rawgeti(L, -1, i + 1);
a[i] = lua_tointeger(L, -1);
lua_pop(L, 1); //弹出上述压栈元素,注意操作栈内元素大部分通过压栈,然后取出,最后通过pop还原栈状态
}
for (int i = 0; i < len; ++i) {
//*方法一,易理解,压入键,压入值
lua_pushinteger(L, i + 1);
lua_pushinteger(L, a[i] + 1);
lua_settable(L, -3);//将stack.top()元素作为值,-2位置元素作为键,放到-3位置的table中
//*/
/*方法二
lua_pushinteger(L, a[i] + 1); //元素压入栈顶
lua_rawseti(L, -2, i + 1); //放到-2位置表中,设置索引为i+1对应的值,并从栈顶弹出
//*/
}
return 0;
}
static int lua_table_return_incrbyone(lua_State *L) {
int len = luaL_len(L, 1);
int a[len];
for (int i = 0; i < len; ++i) {
lua_rawgeti(L, 1, i + 1);
a[i] = lua_tointeger(L, -1);
lua_pop(L, 1);
}
lua_newtable(L); //返回新表的话要新建一个table
for (int i = 0; i < len; ++i) {
lua_pushinteger(L, i + 1);
lua_pushinteger(L, a[i] + 1);
lua_settable(L, -3);
}
return 1;
}
static int lua_table_kv(lua_State *L) {
lua_getfield(L, -1, "name"); //取栈顶table中字段为"name"的值, 并压栈
const char *name = lua_tostring(L, -1); //name拿到,原谅我没用到,只是演示操作
lua_pop(L, 1); //将上述压入栈顶的元素弹出
lua_getfield(L, -1, "age");
int age = lua_tointeger(L, -1);
lua_pop(L, 1);
lua_getfield(L, -1, "score");
int len = luaL_len(L, -1);
int a[len];
for (int i = 0; i < len; ++i) {
lua_rawgeti(L, -1, i + 1);
a[i] = lua_tointeger(L, -1);
lua_pop(L, 1);
}
lua_pop(L, 1);
lua_pushstring(L, "Red"); //”Red"压栈
lua_setfield(L, -2, "name"); //设置-2位置"name"的值为栈顶元素“Red”,并将栈顶元素弹出
lua_pushinteger(L, 17);
lua_setfield(L, -2, "age");
lua_newtable(L);
for (int i = 0; i < len; ++i) {
lua_pushinteger(L, i+1);
lua_pushinteger(L, a[i]+1);
lua_settable(L, -3);
}
lua_setfield(L, -2, "score");
return 0;
}
//lua函数和c层函数建立映射关系
static const struct luaL_Reg funarr[] = {
{"add", lua_add},
{"table_incrbyone", lua_table_incrbyone},
{"table_return_incrbyone", lua_table_return_incrbyone},
{"table_kv", lua_table_kv},
{NULL, NULL}, //这是个末尾哨兵,好像不加也没事。。。。
};
//编译后会创建一个lualib.so库,给lua调用
int luaopen_lualib(lua_State *L) {
/*
再多解释也莫过于luaL_newlib的官方说明,官方手册连接:https://www.lua.org/manual/5.3/
void luaL_newlib (lua_State *L, const luaL_Reg l[]);
Creates a new table and registers there the functions in list l.
It is implemented as the following macro:
(luaL_newlibtable(L,l), luaL_setfuncs(L,l,0))
The array l must be the actual array, not a pointer to it.
*/
luaL_newlib(L, funarr);
return 1;
}
2、test.lua
local lualib = require "lualib"
print("===========两数相加例子===========")
local sum = lualib.add(3, 4)
print("sum", sum)
print("\n\n===========传递表(对原来的表操作)例子===========")
local a = {1, 2, 3, 4, 5}
lualib.table_incrbyone(a)
for i = 1, #a do
print("a["..i.."]", a[i])
end
print("\n\n===========传递表(表中数据操作后返回新表)例子===========")
local a = {1, 2, 3, 4, 5}
local b = lualib.table_return_incrbyone(a)
for i = 1, #b do
print("b["..i.."]", b[i])
end
print("\n\n===========传递键值对例子===========")
local c = {
name = "Blue",
age = 18,
score = {80, 90}
}
lualib.table_kv(c)
for k,v in pairs(c) do
if type(v) ~= "table" then
print("k", k, "v", v)
else
print("k", k)
for kk, vv in pairs(v) do
print("kk", kk, "vv", vv)
end
end
end
3、makefile文件
PLATS = linux macosx
none :
@echo "Please do 'make PLATFORM' where PLATFORM is one of these:"
@echo "$(PLATS) "
linux:
gcc -std=c99 -fPIC -shared -o test.c
lua test.lua
macosx:
gcc -c test.c
gcc -O2 -bundle -undefined dynamic_lookup -o lualib.so test.o
rm -rf *.o
lua test.lua
此处提供mac、linux编译方法,windows还没去研究哈哈哈,mac下用make macosx指令编译,linux下用make linux指令编译。只修改test.lua文件的话,只需lua test.lua运行lua文件,不需要重新编译;
4、运行输出
Blue:LuaCAPI Walker$ make macosx
gcc -c test.c
gcc -O2 -bundle -undefined dynamic_lookup -o lualib.so test.o
rm -rf *.o
lua test.lua
===========两数相加例子===========
sum 7
===========传递表(对原来的表操作)例子===========
a[1] 2
a[2] 3
a[3] 4
a[4] 5
a[5] 6
===========传递表(表中数据操作后返回新表)例子===========
b[1] 2
b[2] 3
b[3] 4
b[4] 5
b[5] 6
===========传递键值对例子===========
k name v Red
k score
kk 1 vv 81
kk 2 vv 91
k age v 17