C++与lua之互调问题

C++链接lua动态库出错

C++调用lua API需要链接lua动态库,如果C++程序无法寻找到动态库路径,运行程序就会出现以下错误:

error while loading shared libraries: liblua.so: cannot open shared object file: No such file or directory

对于此错误,有如下三个解决方案:

  1. 配置lua路径至环境变量
    详情参看博文:Linux配置运行环境
  2. 将lua相关文件拷贝至用户目录
    详情参看博文:Linux配置运行环境
  3. 在编译命令之中向链接器传递附加库目录参数
    编译命令如下所示:
g++ main.cpp -o uninet -Isrc/lua/include -Lsrc/lua/lib -llua -Wl,-rpath=src/lua/lib

# -Wl
# gcc参数,使编译器把之后的参数传递给链接器
# -rpath
# 1. 添加一个目录作为运行时库的搜索路径,在将ELF可执行文件与共享对象链接时使用此选项
# 2. 在链接时,一些动态库明确的链接其他动态库,则此选项也可用于定位这些链接的动态库
# 3. 在运行链接时,会优先搜索此路径,再去搜索LD_RUN_PATH的路径

lua加载C++动态库出错

package.cpath = "./lib/c/?.so"    -- 搜寻路径
local service = require "sqlconnector"    -- 加载模块

在lua中,使用require加载C++动态库时,出现如下错误:

PANIC: unprotected error in call to Lua API (error loading module ‘sqlconnector’ from file ‘./sqlconnector.so’:
./sqlconnector.so: undefined symbol: luaopen_sqlconnector)

使用require加载动态库,其入口函数有规律。
当加载动态库sqlconnector.so时,其入口函数名必须是luaopen_sqlconnetor。

而使用package.loadlib加载动态库,需要指定入口函数名,因此可以自定义入口函数名。

local loadlib = package.loadlib("./lib/c/sqlconnector.so", "luaopen_sqlconnector")    -- 加载注册函数
local service = loadlib()    -- 执行注册函数,创建并返回新表

C++与lua互调的多虚拟机错误

初始编译的sqlconnector.so依赖于liblua.a,而C++入口程序依赖于liblua.so。
当C++通过lua调用sqlconnector.so时,出现以下错误:

PANIC: unprotected error in call to Lua API (multiple Lua VMs detected)

liblua.a是静态库,liblua.so是动态库。
静态库会被编译进程序模块文件,每个模块都单独拥有虚拟机,于是内存之中同时存在多个不同虚拟机。
而动态共享库只会被加载一次,在内存中只存在一份,供给不同程序不同模块共享调用。
若同时使用lua的静态库和动态库,内存之中同样存在多个lua虚拟机,导致多lua虚拟机冲突问题。
以上错误的解决方案是依赖于liblua.so编译sqlconnector.so和C++入口程序。

此外,动态编译lua解释器,不能静态编译lua解释器,否则在调用C模块之时也会出现以上错误。

如果lua采用静态编译,即包含lua静态库,在执行时加载一个lua虚拟机,当lua调用C模块时,由于C模块在编译之时,需要指定lua的静态库或者动态库,再加载一个lua虚拟机,此时存在多个lua虚拟机,造成冲突。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值