原文链接:https://blog.csdn.net/DeliaPu/article/details/114406620
上一篇介绍了如何在C++中调用Lua函数:C++调用Lua函数
本篇介绍反方向调用:通过Lua调用C++动态库中的函数。
定义一套C++函数,我们给它取名叫testlib.cpp:
// testlib.cpp
#include
#include "cpp_lib.h"
using namespace std;
/* 定义C++的Average 函数 */
int average(lua_State *L)
{
int num = lua_gettop(L); //获取参数个数
double sum = 0;
double avg = 0;
for(int i = 1; i <= num; i++) //注意Lua栈下标从1开始
{
sum += lua_tonumber(L, i); //求和
}
avg = sum / num; //求平均
lua_pushnumber(L, avg); //平均值入栈
lua_pushnumber(L, sum); //和入栈
return 2; //return 返回值个数
}
/* 定义C++的sub函数 */
int sub(lua_State *L)
{
int num = lua_gettop(L);
if(num != 2)
{
cout << "Input param number is not correct!" << endl;
return 0;
}
int a = lua_tonumber(L, 1); //获取第一个参数,被减数
int b = lua_tonumber(L, 2); //获取第二个参数,减数
int diff = a - b;
lua_pushnumber(L, diff); //结果压入栈
return 1;
}
/* 定义C++的add函数 */
int add(lua_State *L)
{
int num = lua_gettop(L);
if(num != 2)
{
cout << "Input param number is not correct!" << endl;
return 0;
}
int a = lua_tonumber(L, 1); //获取第一个参数,被减数
int b = lua_tonumber(L, 2); //获取第二个参数,减数
int sum = a + b;
lua_pushnumber(L, sum); //结果压入栈
return 1;
}
//使用luaL_Reg注册新的C函数到Lua中
static luaL_Reg test_functions[] =
{
{"average", average},
{"add", add},
{"sub", sub},
{NULL, NULL} 数组中最后一对必须是{NULL, NULL},用来表示结束
};
/* luaopen_XXX,XXX为库名称,若库名称为testlib.so,XXX即为testlib */
int luaopen_testlib(lua_State *L)
{
luaL_newlib(L, test_functions); //Lua 5.2之后用luaL_newlib代替了luaL_register
return 1;
}
//testlib.h
#pragma once
#include "lua.hpp"
extern "C" int luaopen_testlib(lua_State *L);
将以上CPP代码编译成动态链接库testlib.so:
g++ -std=c++11 -shared -fPIC testlib.cpp -o testlib.so -I/usr/local/include -I. -L/usr/local/lib -llua -ldl
编译成功后,用lua脚本来调用动态链接库中的函数,脚本call_cpplib.lua如下:
--lua call cpp function
local abc = require("testlib")
avg,sum = abc.average(100, 200, 300, 400, 500)
diff = abc.sub(100,50)
total = abc.add(100,50)
print("Average is:" ..avg)
print("Sum is: " ..sum)
print("diff = "..diff)
print("total = "..total)
执行 lua call_cpplib.lua,得到结果:
通过shell脚本执行
luac.sh文件
lua test.lua
chmod 777 luac.sh
在写以上demo的时候,编译testlib.so时出现了编译错误:
hrg@hrg-Default-string:~/delia/lua_demo/demo$ ./build_lib.sh
/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: error adding symbols: Bad value
collect2: error: ld returned 1 exit status
解决方法是,进入到Lua源码中,在Makefile文件的CFLAGS后面添加-fPIC选项,重新编译安装Lua,问题解决。
注:-fPIC 作用于编译阶段,指示编译器产生与位置无关代码(Position-Independent Code), 产生的代码中,没有绝对地址,全部使用相对地址,故而使得代码被加载器加载到内存的任意位置都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。