Lua点滴LuaLua脚本语言开发

lua调用c(lua c api 5.3版本)

2018-03-07  本文已影响14人  90d81be3ec65

一、附上手册,供读者查阅

二、预备知识

三、代码如下

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
上一篇 下一篇

猜你喜欢

热点阅读