LUA 与 C

1.7k 词

  • 使用栈进行lua和C数据交换
  • 要将一个值传给lua,需要先将该值压入栈,然后调用lua api函数,lua会从栈中获取该值并从栈中弹出
  • 入栈API

    1
    2
    3
    4
    5
    6
    void lua_pushnil(lua_State *);
    void lua_pushboolean(lua_State *, int bool);
    void lua_pushstring(lua_State *, const char *s);
    void lua_pushlstring(lua_State *, const char *s, size_t len);
    void lua_pushnumber(lua_State *, lua_Number n);// 双精度浮点
    void lua_pushinteger(lua_State *, lua_Integer n);// 整型,足以存储大型字符串长度,定义为ptrdiff_t类型
  • 栈大小:默认20(LUA_MINSTACK定义),通过如下代码检查栈大小

    1
    int lua_checkstack(lua_State *, int sz)

查询

  • 通过索引查找栈中元素:1栈底,2次栈底,-1表示栈顶,-2次栈顶

    1
    lua_tostring(L, -1);// 将栈顶元素弹出转换为string
  • 检查栈元素类型

    1
    2
    int lua_isstring(lua_State *L, int index);
    int lua_isnumber(lua_State *L, int index);
  • 栈元素转换

    1
    int lua_toboolean(lua_State *L, int index);
  • 不要在C函数之外调用在C函数内获取的指向字符串的指针(函数退出清理栈)

C操作栈函数列表

1
2
int lua_getglobal(L, const char *name);//全局变量name值压栈,并返回该值类型
int pcall(L, int paramcount, int resultcount, int err_handler_stackindex);//先删除函数和参数,然后压入结果或者错误

C调用lua函数

  • 待调用函数入栈,并压入参数,然后使用pcall调用,最后将结果从栈中弹出。
    1
    2
    3
    function (x, y)
    reutrn x + y
    end
  • 调用代码示例(前提需要打开库,并运行了以上lua代码):
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    int callluaFunc(int x, int  y)
    {
    int ret = 0;
    lua_getglobal(L, "luaf");
    lua_pushnumber(L, x);
    lua_pushnumber(L, y);
    // 执行调用,2个参数1个结果
    if (lua_pcall(L, 2, 1, 0))
    error(L, "error running function:%s", lua_tostring(L, -1));
    // 检查结果
    if (!lua_isnumber(L, -1))
    error(L, "result need to be number");

    ret = lua_tonumber(L, -1));
    lua_pop(L, 1);
    return ret;
    }

LUA调用C

  • typedef int (lua_CFunction)(lua_State L);// 返回压入栈中结果数量,方便与栈中其余值区分

  • 调用前需要提前注册c函数

    1
    void lua_pushfunction(L, lua_CFuntion);
  • 示例:

    1
    2
    lua_pushfunction(L, c_function);// 压入函数
    lua_setglobal(L, "cfunctionname");//出栈,将函数赋予全局变量cfuntionname中
  • require “myclib” 过程:链接动态库到lua,并寻找luaopen_myclib函数,将其注册为一个lua函数,然后调用它以打开模块

userdata

  • lua_newuserdata
    1
    2
    void lua_newuserdata(lua_State *L, size_t sz);
    这个函数分配一块指定大小的内存块, 把内存块地址作为一个完全用户数据压栈, 并返回这个地址。 宿主程序可以随意使用这块内存