IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> Lua调用C的动态库 -> 正文阅读

[C++知识库]Lua调用C的动态库

项目背景:
因为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
在这里插入图片描述

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-12-26 21:57:27  更:2021-12-26 21:59:44 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 11:26:14-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码