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


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

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

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

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

1. 例程

定义一套C++函数,我们给它取名叫testlib.cpp:

// testlib.cpp
 
#include <iostream>
#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

在这里插入图片描述

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

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于Lua调用Mosquitto库,需要使用Lua的C API进行封装,然后通过Lua脚本进行调用。Mosquitto库提供了一些函数,其中mosquitto.new函数用于创建一个Mosquitto客户端实例。下面是该函数的详细解释: 函数原型: ```c struct mosquitto *mosquitto_new(const char *id, bool clean_session, void *userdata) ``` 函数参数: - id:字符串类型,表示客户端标识符,如果id为NULL,则Mosquitto库将自动为客户端生成一个唯一的标识符。 - clean_session:布尔类型,表示是否启用清除会话功能。如果设置为true,则在客户端断开连接时,Mosquitto服务器将删除与客户端相关的所有信息。如果设置为false,则在客户端断开连接时,Mosquitto服务器将保留与客户端相关的信息,以便客户端重新连接。 - userdata:指针类型,表示用户数据,可以传递任何类型的数据,Mosquitto库不会对其进行处理,只是简单地将其传递给回调函数,以便用户在回调函数中使用。 函数返回值: - 成功:返回一个指向mosquitto结构体的指针,表示创建的Mosquitto客户端实例。 - 失败:返回NULL,表示创建失败。 示例代码: ```c #include <mosquitto.h> #include <stdio.h> int main(int argc, char *argv[]) { struct mosquitto *mosq = NULL; mosq = mosquitto_new("client1", true, NULL); if(mosq){ printf("Mosquitto client created successfully.\n"); mosquitto_destroy(mosq); }else{ printf("Failed to create Mosquitto client.\n"); } return 0; } ``` 在上面的示例代码中,我们创建了一个名为client1的Mosquitto客户端实例,并启用了清除会话功能。如果创建成功,则打印“Mosquitto client created successfully.”,否则打印“Failed to create Mosquitto client.”。最后,我们使用mosquitto_destroy函数销毁Mosquitto客户端实例,释放内存。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值