Lua调用C++动态链接库.so

Lua调用C++动态链接库.so

  • 通过Lua调用C++动态库中的函数
    • 1. 例程
    • 头文件testlib.h
    • 2. 遇到的问题


通过Lua调用C++动态库中的函数

原文链接:https://blog.csdn.net/DeliaPu/article/details/114406620

上一篇介绍了如何在C++中调用Lua函数:C++调用Lua函数

本篇介绍反方向调用:通过Lua调用C++动态库中的函数。

1. 例程

定义一套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

//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

Lua调用C++动态链接库.so_第1张图片

2. 遇到的问题

在写以上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), 产生的代码中,没有绝对地址,全部使用相对地址,故而使得代码被加载器加载到内存的任意位置都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。

你可能感兴趣的:(脚本语言,lua,c++,开发语言)