Lua 模块与包 调用c程序.so文件

模块类似于一个封装库,从 Lua 5.1 开始,Lua 加入了标准的模块管理机制,可以把一些公用的代码放在一个文件里,以 API 接口的形式在其他地方调用,有利于代码的重用和降低代码耦合度。

Lua 的模块是由变量、函数等已知元素组成的 table,因此创建一个模块很简单,就是创建一个 table,然后把需要导出的常量、函数放入其中,最后返回这个 table 就行。以下为创建自定义模块 m.lua,文件代码格式如下:

-- 文件名为 m.lua
-- 定义一个名为 m 的模块
module = {}
 
-- 定义一个常量
module.constant = "这是一个常量"
module.table = {key1="val1","val2"}
 
-- 定义一个函数
function module.func1()
    io.write("这是一个公有函数!\n")
end
 
local function func2()
    print("这是一个私有函数!")
end

 
function module.func3()
    func2()
end

module.func4 = func2;

module.func5 = function()
    print("func5!!!")
end
 
return module

加载机制

对于自定义的模块,模块文件不是放在哪个文件目录都行,函数 require 有它自己的文件路径加载策略,它会尝试从 Lua 文件或 C 程序库中加载模块。

require 用于搜索 Lua 文件的路径是存放在全局变量 package.path 中,当 Lua 启动后,会以环境变量 LUA_PATH 的值来初始这个环境变量。如果没有找到该环境变量,则使用一个编译时定义的默认路径来初始化。

当然,如果没有 LUA_PATH 这个环境变量,也可以自定义设置,在当前用户根目录下打开 .profile 文件(没有则创建,打开 .bashrc 文件也可以),例如把 "~/lua/" 路径加入 LUA_PATH 环境变量里:

export LUA_PATH="~/lua/?.lua;;"
//文件名为luaLoad.c,定义一个可供lua调用的模块
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>

static int add(lua_State *L) {
    double d1 = luaL_checknumber(L, 1);  
    double d2 = luaL_checknumber(L, 2);  
    lua_pushnumber(L, d1+d2);  
    return 1;  
}
int luaopen_luaLoad(lua_State *L) {
    luaL_Reg luaLoadFun[] = {
        {"add",add},
        {NULL,NULL}
    };
    luaL_newlib(L,luaLoadFun);
    return 1;
}

编译上面这个luaLoad.c文件为luaLoad.so文件

gcc luaLoad.c -fPIC -shared -o luaLoad.so -I/home/ubuntu/Downloads/lua-5.3.4/src

-I后面是lua的安装路径,里面包含了上面include的那几个头文件

--testModule.lua测试调用上面两个模块
local luaLoad = require "luaLoad"
print(luaLoad.add(1,2))

local m = require("m")

print(m.constant)
for key,val in pairs(m.table) do
    print(key,val)
end

m.func1()
m.func3()
m.func4()
m.func5()
m.func2()
ubuntu@dongyang-K46CB:~/lua$ lua testModule.lua

3.0
这是一个常量 1 val2 key1 val1
这是一个公有函数! 这是一个私有函数! 这是一个私有函数! func5!!! lua: testModule.lua:15: attempt to call a nil value (field 'func2') stack traceback: testModule.lua:15: in main chunk [C]: in ?