Lua调用C的动态库

这篇博客介绍了Lua与C++的交互,特别是在线程调用和协程使用上的问题。由于Lua的单线程特性,无法直接调用C的多线程函数。示例展示了如何使用Python替代Lua来管理线程。同时,文章通过代码示例解释了Lua的函数、table操作、元表以及调用C库的方法。在尝试通过Lua调用C库中的多线程函数时,遇到了线程无法启动以及Lua协程结束导致C库线程同步结束的问题。
摘要由CSDN通过智能技术生成

项目背景:
因为lua是单线程的,每个lua执行就相当于是一个线程,因此是没有办法完成调用两个C线程的,不能满足当前项目需求,因此不使用lua脚本的方式进行CDLL的线程调用管理了,而使用python了。

1、 lua基础

https://www.runoob.com/lua/lua-tutorial.html

--两个点表示连接
print("两个点表示连接")
a = "1212" .. "nihao"
print(a)


--测试function及forif语法
print("测试function及for和if语法")
local function maxs(a)
	local maxi = 1
	local maxnum = a[maxi]
	for i, val in ipairs(a) do
		if val > maxnum then
			maxi = i
			maxnum = val
		end
	end
	return maxi, maxnum
end
print(maxs({8,10,23,12,5,0}))


--table的concat测试
local fruits = {"banana", "orange", "apple"}
print("连接后的字符串", table.concat(fruits))
print("指定连接字符后的字符串", table.concat(fruits, ", "))
print("指定索引来连接table的字符串", table.concat(fruits, ", ", 2, 3))

--测试函数传参可变参数
print("测试函数传参可变参数")
function add(...)
	local s = 0
	local arg = {...}
	for i, v in ipairs{...} do --> {...} 表示一个由所有变长参数构成的数组
		s = s+v
	end
	print("总共传入 " .. select("#",...) .. " 个数")
	print("传入" .. #arg .. "数字")
	return s
end
print(add(1,2,3,4,5,6,7,0))

--获取参数总数
function foo(...)
	for i = 1, select('#', ...) do
		local arg = select(i, ...) --> select(n,) 可以访问第 n 个到数组最后的参数
		print("arg", arg)
	end
end
print(foo(1,2,3,4))


--运算符.. #
a = "Hello "
b = "World"
print("连接字符串 a 和 b ", a..b )
print("b 字符串长度 ",#b )


--测试模块
《module.lua文件》
module = {}
module.constant = "这是一个变量"
function module.func1()
	io.write("这是一个公有函数!\n")
end
local function func2()
	print("这是一个私有函数")
end

function module.func3()
	func2()
end
return module
《main.lua文件》
local m = require("module") --> 别名
m.func1();
m.func3();
print(m.constant)

--测试元表的__index
print("测试元表的__index")
mytable = setmetatable({key1 = "value1"}, {__index = {key2 = "metatablevalue"}})
print(mytable.key1, mytable.key2)

--测试元表的相加
function table_maxn(t)
	local mn = 0
	for k, v in pairs(t) do
		if mn < k then
			mn = k
		end
	end
	return mn
end
mytable = setmetatable({1, 2, 3}, {
	__add = function(mytable, newtable)
	for i = 1, table_maxn(newtable) do
		table.insert(mytable, table_maxn(mytable)+1, newtable[i])
	end
	return mytable
end
})
secondtable = {4, 5, 6}
mytable = mytable + secondtable
for k, v in ipairs(mytable) do
	print(k, v)
end

2、 C调用lua,执行lua脚本

复制lua源码到工程中或者引入lua的lib文件及头文件也可。
在这里插入图片描述

#include <windows.h> 

extern "C" {
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}

int main()
{
	lua_State* l = luaL_newstate();
	luaL_openlibs(l);
	luaL_dofile(l, "main.lua");
	lua_close(l);
	system("pause"); //为了保证在windows资源管理器中打开main.exe不闪退。需要windows.h。
	return 0;
}

3、lua调用C库

在这里插入图片描述
c工程

extern "C" {
#include "lua.h"  
#include "lualib.h"  
#include "lauxlib.h"
};
#include <thread>
#include <iostream>  
using namespace std;

int number = 0;
int number2 = 0;
int flag = 0;
std::thread *t1 = NULL;
std::thread *t2 = NULL;
void ThreadProc1()
{
	flag = 1;
	while (1)
	{
		cout << "thread 1 :" << number << endl;
		++number;
		this_thread::sleep_for(std::chrono::milliseconds(10));
	}

	return ;
}
void ThreadProc2()
{
	while (number2 < 100)
	{
		cout << "thread 2 :" << number2 << endl;
		++number2;
		this_thread::sleep_for(std::chrono::milliseconds(10));
	}

	return ;
}

extern "C" int ShowMsg(lua_State* luaEnv) {
	cout << "Hello world from clibs!" << endl;
	t1 = new std::thread(ThreadProc1);
	return 1; // 返回值个数为0个.  
}
extern "C" int ShowMsg2(lua_State* luaEnv) {
	cout << "Hello world from clibs222!" << endl;
	t2 = new std::thread(ThreadProc2);

	return 0; // 返回值个数为0个.  
}
// part one: 要导出的函数列表
static luaL_Reg luaLibs[] = {
	{ "ShowMsg", ShowMsg },
	{ "ShowMsg2", ShowMsg2 },
	{ NULL, NULL }
};

// part two: DLL入口函数,Lua调用此DLL的入口函数.  
//testDll是modole名, 将来require这个名字并且这个名称要与dll名称一致,并且不能与lua名称一致
extern "C" __declspec(dllexport)
int luaopen_testDll(lua_State* luaEnv) {   
	const char* const LIBRARY_NAME = "WinFeature"; //这里也写WinFeature
	luaL_register(luaEnv, LIBRARY_NAME, luaLibs);//注册要导出的函数列表
	return 1;
}

lua文件

--加载test库
WinFeature1 = require("testDll")

--定义协程
co = coroutine.create(
    function()
		WinFeature1.ShowMsg()
    end
)

--激活协程
coroutine.resume(co)
--打印协程状态
print(coroutine.status(co))


4、lua无法调起C库中两个线程,以及lua端卡死问题或者lua端协程结束C也跟着结束

在这里插入图片描述
lua函数

--加载test库
WinFeature1 = require("testDll")

function Sleep(n)
   local t0 = os.clock()
   while os.clock() - t0 <= n do end
end

--定义协程
co = coroutine.create(
    function()
		WinFeature1.ShowMsg()
		while true do
			print("coroutine")
			Sleep(0.1)
		end
    end
)

--激活协程
coroutine.resume(co)
--打印协程状态
print(coroutine.status(co))


参考博客:

https://blog.csdn.net/qq_35807952/article/details/79912769 Lua与C++交互初探之Lua调用C++
https://www.runoob.com/lua/lua-tutorial.html Lua 教程
https://www.cnblogs.com/chechen/p/11415104.html VS2015 创建C++动态库及使用
https://blog.51cto.com/u_1433795/1310702 lua 调用C++ DLL函数简单实例
https://www.kancloud.cn/thinkphp/lua-guide/43809 绑定Lua和C/C++的库

检测动态库中导出的函数列表
dumpbin /exports testDll.dll
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值