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

緣起

luaL_setfuncs 這個函數能夠註冊c函數到lua,另外還能夠設置閉包函數使用的變量upvalue. 我沒有用過,在 雲風的skynet 才第一次見過,因而寫個例子實際使用如下.linux

函數原型:

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

文檔定義:

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

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源碼並編譯ui

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 <lua.h>
#include <lauxlib.h>

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.solua

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的做用.centos7

相關文章
相關標籤/搜索