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
对于此错误,有如下三个解决方案:
- 配置lua路径至环境变量
详情参看博文:Linux配置运行环境 - 将lua相关文件拷贝至用户目录
详情参看博文:Linux配置运行环境 - 在编译命令之中向链接器传递附加库目录参数
编译命令如下所示:
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虚拟机,造成冲突。


361

被折叠的 条评论
为什么被折叠?



