lua5.3中luaL_setfunc设置upvalue的用法示例

https://www.cnblogs.com/cheerupforyou/p/7192307.html

缘起

luaL_setfuncs 这个函数可以注册c函数到lua,另外还可以设置闭包函数使用的变量upvalue. 我没有用过,在 云风的skynet 才第一次见过,于是写个例子实际使用以下.

函数原型:

void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup);

文档定义:

Registers all functions in the array l (see luaL_Reg) into the table on the top of the stack (below optional upvalues, see next).

When nup is not zero, all functions are created sharing nup upvalues, which must be previously pushed on the stack on top of the library table. These values are popped from the stack after the registration.

意思是第三个参数 nup 如果非零, 则所有通过luaL_setfuncs注册的函数都共享 nup个 upvalues. 这些 upvalues 必须在注册之前 pushed 到栈上.

实例

实例是在lua5.3环境下面,编写导处的一个lua能用动态库.

环境搭建

我用的centos7.0,自带lua5.1.下载5.3源码并编译

wget https://www.lua.org/ftp/lua-5.3.4.tar.gz
tar -xzvf lua-5.3.4.tar.gz
cd lua-5.3.4
make linux 

编写要导出的lua库
lua_mytest.c
#include 
#include 

static int add(lua_State *L){
    double op1 = luaL_checknumber(L,1);
    double op2 = luaL_checknumber(L,2);
    //将函数的结果压入栈中。如果有多个返回值,可以在这里多次压入栈中。
    lua_pushnumber(L,op1 + op2);
    //返回值用于提示该C函数的返回值数量,即压入栈中的返回值数量。
    return 1;
}

static int add_with_upvalue(lua_State *L){
    int k = lua_tonumber(L, lua_upvalueindex(1));
    const char* another_upvalue = lua_tostring(L, lua_upvalueindex(2));
    printf("second upvalue is %s\n",another_upvalue);

    double op1 = luaL_checknumber(L,1);
    double op2 = luaL_checknumber(L,2);
    //将函数的结果压入栈中。如果有多个返回值,可以在这里多次压入栈中。
    lua_pushnumber(L,op1 + op2+k);
    //返回值用于提示该C函数的返回值数量,即压入栈中的返回值数量。
    return 1;
}

static const luaL_Reg no_upvalue_func[] = {
    {"add", add},
    {0, 0}
};

static const luaL_Reg with_upvalue_func[] = {
    {"add_with_upvalue", add_with_upvalue},
    {0, 0}
};
LUALIB_API int luaopen_mytest(lua_State * L) {
    lua_newtable(L);
    /*register function no upvalue*/
    luaL_setfuncs(L, no_upvalue_func, 0);

    /*set two upvalue */
    lua_pushnumber(L,100);
    lua_pushstring(L,"i am upvalue");
    /*register function with two upvalue*/
    /*push了两个upvalue值所以第三个参数是2*/
    luaL_setfuncs(L, with_upvalue_func, 2);
    return 1;
}

MyMakeFile 编译mytest.so
all:
    gcc -Wall -O2 -shared -o mytest.so lua_mytest.c -fPIC -llua -I. -lm -L/home/gsx/work/lua_study/lua-5.3.4/src
clean:
    rm -f mytest.so

执行命令 make -f MyMakeFile ,生成mytest.so

test.lua
local mytest = require "mytest"

ret = mytest.add(10,20)
print(ret)

ret = mytest.add_with_upvalue(10,20)
print(ret)

测试
lua test.lua
output:
30.0
second upvalue is i am upvalue
130.0

注意事项
  1. test.lua 和 mytest.so放在同一个目录.
  2. 如果编译mytest.so的过程中报错. /usr/bin/ld: /usr/local/lib/liblua.a(lapi.o): relocation R_X86_64_32 against `luaO_nilobject_' can not be used when making a shared object; recompile with -fPIC /usr/local/lib/liblua.a: could not read symbols: Bad value, 则重新编译 liblua.a,在 lua的MakeFile 的CFLAG里面增加 -fPIC即可.

总结

例子通过注册一个不带有upvalue和带有两个upvalue的简单函数说明了luaL_setfuncs的作用.

你可能感兴趣的:(lua5.3中luaL_setfunc设置upvalue的用法示例)