1. 程式人生 > >Lua:模組、使用位操作BitOp、C API(Lua與C互相呼叫)

Lua:模組、使用位操作BitOp、C API(Lua與C互相呼叫)

一、模組

1.1 概述

建立一個模組最簡單的方法是:

        1. 建立一個table;

        2. 並將所有需要匯出的函式放入其中;

        3. 最後返回這個table。

1.2 程式碼

檔案:test.lua

complex = {}

function complex.add(x, y)
        return x+y
end

return complex

1.2 執行結果

載入模組:require (“test”)


二、使用位做操

1.1 Lua位操作

Lua不支援位操作,需要單獨下載位操作的模組BitOp。

1.2 下載、安裝位操作模組

下載:

檔名:LuaBitOp-1.0.2.tar.gz

安裝:

        tar zxvf LuaBitOp-1.0.2.tar.gz

        cd LuaBitOp-1.0.2

        make  (可能需要修改bit.c中包含的lua.h檔案的路徑)

        make install

1.3 使用位操作

載入模組:require (“bit”)


三、Lua呼叫C函式

3.1 程式碼:將C函式寫成模組

#include <stdio.h>
#include <string.h>
#include "/root/LuaJIT-2.0.2/src/lua.h"
#include "/root/LuaJIT-2.0.2/src/lauxlib.h"
#include "/root/LuaJIT-2.0.2/src/lualib.h"

static int c_add(lua_State* L)
{
    //1. 檢查棧中的引數是否合法,1表示Lua呼叫時的第一個引數(從左到右),依次類推。
    //1. 如果Lua程式碼在呼叫時傳遞的引數不為number,該函式報錯並終止程式執行。
    double op1 = luaL_checknumber(L,1);
    double op2 = luaL_checknumber(L,2);

    //2. 將函式的結果壓入棧中。
    //2. 如果有多個返回值,可以在這裡多次壓入棧。
    lua_pushnumber(L,op1 + op2);

    //3. 返回值用於提示該C函式的返回值數量,即壓入棧中的返回值數量
    return 1;
}

static const struct luaL_Reg test[] = {
    {"add", c_add},
    {NULL, NULL}
};

//宣告一個主函式
LUALIB_API int luaopen_test(lua_State* L)
{
    luaL_register(L,"test",test);
    return 1;
}

3.2 編譯

        寫完C模組後,必須將其連結到直譯器。

        必須將C程式碼編譯成動態連結庫。

將C程式碼編譯成動態庫:

        gcc -fPIC -O2 -fomit-frame-pointer -Wall  -I/usr/local/include  -c -o test.o test.c

        gcc -shared -fPIC  -o test.so test.o

將動態庫拷貝到Lua的lib目錄下:

        cp test.so /usr/lib64/lua/5.1/

3.3 Lua中呼叫C函式

和呼叫Lua模組中函式一樣:require ("test")


四、C呼叫Lua函式

4.1 程式碼

兩個公共:

        lua作為配置檔案,被C讀取;

        lua中有lua函式,被C呼叫執行。

配置檔案:data.lua

width = 200
height = 300


add = function (x, y)
        return x + y
end

程式碼檔案:test.c

#include <stdio.h>
#include <stdlib.h>

#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"

int add(lua_State *L, int x, int y)
{
        lua_getglobal(L, "add");
        lua_pushnumber(L, x);
        lua_pushnumber(L, y);

        if (lua_pcall(L, 2, 1, 0) != 0)
        {
                error(L, "error running function 'add':%s\n", lua_tostring(L, -1));
        }

        if (!lua_isnumber(L, -1))
        {
                error(L, "function 'add' must return a number.\n");
        }

        int z = lua_tonumber(L, -1);

        lua_pop(L, 1);

        return z;
}

int main(int argc, char*argv[])
{
        lua_State *L = luaL_newstate();
        luaL_openlibs(L);

        //0. load lua config
        if (luaL_loadfile(L, "/root/1103/data.lua") || lua_pcall(L, 0, 0, 0))
                error(L, "cann't:%s", lua_tostring(L, -1));

        //1. read lua variable
        lua_getglobal(L, "width");
        lua_getglobal(L, "height");

        if (!lua_isnumber(L, -2))
                error(L, "'width' should be a number.");
        if (!lua_isnumber(L, -1))
                error(L, "'height' should be a number.");

        int w = lua_tointeger(L, -2);
        int h = lua_tointeger(L, -1);

        printf("width:%d, height:%d\n", w, h);

        //2. read and run lua function
        int sum = add(L, 10, 4);

        printf("sum:%d\n", sum);

        lua_close(L);

        return 0;
}

4.2 編譯

        gcc -o test test.c -I /usr/local/luajit/include/luajit-2.1 -L /usr/local/luajit/lib -l luajit-5.1

4.3 執行結果


參考資料: