lua调用C/C++的函数,十分钟快速掌握
系列文章目录
lua调用C\C++动态库函数
- 系列文章目录
- 摘要
- 环境
- 使用步骤
- 你需要有个lua环境
- 引入库
- 码代码
- lua代码
摘要
在现代软件开发中,Lua作为一种轻量级脚本语言,在游戏开发、嵌入式系统等领域广泛应用。Lua与C/C++的高度集成使得开发者能够借助其灵活性和高效性实现更强大的功能。本文将通过一些简单、直接的示例探讨Lua调用C/C++函数的技术。Lua通过调用C/C++实现的extern "C"函数来交互,首先,我们需要在C/C++中编写适当的包装函数,并使用Lua API将其注册到Lua虚拟机中,这一过程包括参数的传递、函数调用以及返回值的处理。通过合理设计的接口,生成动态库文件使其在lua脚本中用require引用,我们能够在Lua中直接调用C/C++函数,实现跨语言的功能扩展。这为项目提供了更大的灵活性,允许开发者在Lua中编写高层逻辑,同时利用C/C++的性能优势处理底层任务。从实践角度看,Lua调用C/C++的技术架构在提高代码可维护性和性能的同时,也为项目带来了更强大的扩展性。通过深入学习Lua与C/C++交互的原理和最佳实践,开发者可以更好地应用这一技术,提升项目的开发效率和整体性能。
还有一种提供C API给lua用的方法:把lua的源码clone一份自己改,定义一个library导出,然后编译成可执行文件或者库,那么lua依然可以通过require引入和使用。
提示:以下是本篇文章正文内容,下面案例可供参考
环境
| 软件 | 版本 |
|---|---|
| Windows | 10 |
| visual studio | 2022 |
| lua | 5.1 |
| C++ | 17 |
使用步骤
你需要有个lua环境
在lua官网下载编译好的动态库、静态库、头文件和可执行二进制文件。
https://luabinaries.sourceforge.net/
拿到lua.hpp头文件和lua5.1.lib静态库,加到自己项目的引用。
引入库
lua.hpp头文件去安装目录找。
码代码
头文件
代码如下(示例):
#pragma once
/*
几个简单的函数
*/// step 1
#include "lua.hpp"// step 2 定义自己的函数
int addTwoNumber(int a, int b)
{return a + b;
}const char* linkNameAndNumber(const char* name, int age)
{std::unique_ptr<char> pbuf(new char[128]);sprintf(pbuf.get(), "Your name is %s, and %d years old.", name, age);std::string r(pbuf.get());std::cout<<"C source output " << r << std::endl;auto rbuf = new char[128];memcpy(rbuf, pbuf.get(), sizeof(pbuf.get()));std::cout << rbuf << " buffer content" << std::endl;return rbuf;
}const wchar_t* wLinkNameAndNumber(const wchar_t* name, int age)
{std::unique_ptr<wchar_t> pbuf(new wchar_t[128]);wsprintf(pbuf.get(), L"Your name is %s, and %d years old.", name, age);std::wstring r(pbuf.get());std::wcout << L"C source output " << r << std::endl;return r.c_str();
}/*** step 3 定义函数的wrapper* \brief origin function* \param L* \return*/
extern "C" int addTwoNumberWrapper(lua_State * L)
{double a, b, sum = 0;int pCount = lua_gettop(L);for (int i = 0; i <= pCount; ++i){if (i == 1){a = lua_tonumber(L, i);}else if (i == 2){b = lua_tonumber(L, i);}}sum = addTwoNumber(a, b);lua_pushnumber(L, sum);return 1;
}extern "C" int linkNameAndNumberWrapper(lua_State * L)
{int pCount = lua_gettop(L);const char* name = lua_tostring(L, 1);int age = lua_tointeger(L, 2);auto result = linkNameAndNumber(name, age);lua_pushstring(L, result);return 1;
}
dllmain.cpp
/*** step 4 定义函数的wrapper注册表* \brief function registry table*/
static luaL_Reg cMethods[] = {{"addTwoNumber", addTwoNumberWrapper},{"linkNameAndNumber", linkNameAndNumberWrapper},{NULL, NULL}
};/*step 5 创建lua_openlibrary函数
*/
extern "C" __declspec(dllexport)
int luaopen_MyMethodLib(lua_State * L)
{std::cout << "=========载入MyMethodLib库======" << std::endl;const char* libName = "MyMethodLib";luaL_register(L, libName, cMethods);return 1;
}
Windows平台生成的动态库可以使用visual studio命令行工具的dumpbin /exports 查看导出符号表,检查函数导出情况。
生成的动态库放到lua安装目录下或者自己的lua脚本目录下。
lua代码
local myMethodLib = require("MyMethodLib")local r1 = myMethodLib.addTwoNumber(1,2)
local r2 = myMethodLib.linkNameAndNumber("Michael",67)print(r1, r2)
使用lua.exe运行脚本即可。
相关文章:
lua调用C/C++的函数,十分钟快速掌握
系列文章目录 lua调用C\C动态库函数 系列文章目录摘要环境使用步骤你需要有个lua环境引入库码代码lua代码 摘要 在现代软件开发中,Lua作为一种轻量级脚本语言,在游戏开发、嵌入式系统等领域广泛应用。Lua与C/C的高度集成使得开发者能够借助其灵活性和高…...
自定义GPT已经出现,并将影响人工智能的一切,做好被挑战的准备了吗?
原创 | 文 BFT机器人 OpenAI凭借最新突破:定制GPT站在创新的最前沿。预示着个性化数字协助的新时代到来,ChatGPT以前所未有的精度来满足个人需求和专业需求。 从本质上讲,自定义GPT是之前的ChatGPT的高度专业化版本或代理,但自定…...
vue中一个页面引入多个相同组件重复请求的问题?
⚠️!!!此内容需要了解一下内容!!! 1、会使用promise??? 2、 promise跟 async 的区别??? async 会终止后面的执行,后续…...
Uniapp连接iBeacon设备——实现无线定位与互动体验(实现篇)
export default { data() { return { iBeaconDevices: [], // 存储搜索到的iBeacon设备 deviceId: [], data: [], url: getApp().globalData.url, innerAudioContext: n…...
【ceph】ceph集群删除pool报错: “EPERM: pool deletion is disabled“
本站以分享各种运维经验和运维所需要的技能为主 《python零基础入门》:python零基础入门学习 《python运维脚本》: python运维脚本实践 《shell》:shell学习 《terraform》持续更新中:terraform_Aws学习零基础入门到最佳实战 《k8…...
【微信小程序】使用npm包
1、小程序对npm的支持与限制2、Vant Weapp通过 npm 安装修改 app.json修改 project.config.json构建 npm 包 3、使用4、定制全局主题样式5、API Promise化 1、小程序对npm的支持与限制 目前,小程序中已经支持使用npm安装第三方包, 从而来提高小程序的开发…...
【开发记录篇】第二篇:SQL创建分区表
实现分区表注意事项 分区字段必须在主键中存在 使用时间分区时,字段类型不支持 timestamp,需改为 datetime 年分区示例 下表中使用 insert_time 时间进行分区 CREATE TABLE t_log (id bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 日志ID,inse…...
vue 使用 this.$router.push 传参数,接参数的 query或params 两种方法示例
背景:vue项目 使用this.$router.push进行路由跳转时,可以通过query或params参数传递和接收参数。 通过query参数传递参数: // 传递参数 this.$router.push({path: /target,query: {id: 1,name: John} }); // 接收参数 this.$route.query.id …...
rk3588 usb网络共享连接
出门在外总会遇到傻 X 地方 没有能连接公网的 网口给香橙派连网 而我的香橙派5plus 没有wifi模块。。。话不多说 在手机上看一眼手机的mac地址, 在rk3588 上执行以下命令: sudo ifconfig usb0 down sudo ifconfig usb0 hw ether 58:F2:FC:5D:D4:7A //该m…...
shell 拒绝恶意连接脚本 centos7.x拒绝恶意连接脚本
1. crontab -l 脚本频率: */2 * * * * /bin/bash /home/shell/deny.sh 2. 脚本: rm -rf /home/shell/ip_list cat /var/log/secure | grep "Failed password for" | awk {print$(NF-3)} | sort | uniq -c > /home/shell/ip_list #cat /va…...
【系统架构设计】计算机公共基础知识: 2 计算机系统基础知识
目录 一 计算机系统组成 二 操作系统 三 文件系统 四 系统性能 一 计算机系统组成...
什么是代理模式,用 Python 如何实现 Proxy(代理 或 Surrogate)对象结构型模式?
什么是代理模式? 代理(Proxy)是一种结构型设计模式,其目的是通过引入一个代理对象来控制对另一个对象的访问。代理对象充当目标对象的接口,这样客户端就可以通过代理对象间接地访问目标对象,从而在访问过程…...
国内领先的五大API接口供应商
API(Application Programming Interface)接口,现在很多应用系统中常用的开放接口,对接相应的系统、软件功能,简化专业化的程序开发。作者用过的国内比较稳定的API接口供应商有如下几家,大家可以参考选择&am…...
第十九章 Java绘图
一,Java绘图类 19.1.1Graphics类 Graphics类是所有图形上下文的抽象基类,它允许应用程序在组件以及闭屏图像上进行绘制。 可实现直线,矩形,多边形,椭圆,圆弧等形状和文本,图片的绘制制作。 …...
【C++面向对象】13. 接口 / 抽象类*
文章目录 【 1. 抽象类 】1.1 抽象类的定义1.2 抽象类的应用条件1.3 实例 【 2. 设计策略 】 接口描述了类的行为和功能,而不需要完成类的特定实现。C 接口是使用 抽象类(abstract base class,也称为ABC) 来实现的。 【 1. 抽象类…...
LeetCode热题100——二分查找
二分查找 1. 搜索插入位置2. 搜素二维矩阵3. 在排序数组中查找第一个和最后一个元素位置 1. 搜索插入位置 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 // 题…...
使用VC++实现分段线性变换,直方图均衡化、锐化处理(使用拉普拉斯算子)
图像锐化1 实验要求 5.1实验目的、要求 实验目的: (1)掌握图像增强的原理与相关方法。 (2)能使用VC实现图像增强的一些相关功能。 实验要求: A部分: (1)对一幅256级灰度…...
react class改hooks写法
类头修改 export default class EditUseTable extends Component 改为 export default function EditUseTable({})参数修改 constructor(props) {super(props)const {dbRecord, type, currentRecord, readOnly, updateTaxAmount} this.props改为(主函数的参数&a…...
桂院校园导航 | 云上高校导航 云开发项目 二次开发教程 1.3
Gitee代码仓库:桂院校园导航小程序 GitHub代码仓库:GLU-Campus-Guide 演示视频 中国大学生计算机设计大赛-移动应用与开发-云上高校导航 升级日志 1.3 优化了小程序的数据存储方式,对部分页面进行了调整,调整了功能和代码。 引…...
sscanf提取相应字符到数组
代码如下 #include<stdio.h> #include<string.h>int main(int argc, char const *argv[]) {char buf[128] {0};int m1 0, m2 0;int s1 0, s2 0;char lrc[128] "";sscanf("[02:16.33][04:11.44]我想大声宣布对你恋恋不舍","[%*1d%d…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...
【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...
HBuilderX安装(uni-app和小程序开发)
下载HBuilderX 访问官方网站:https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本: Windows版(推荐下载标准版) Windows系统安装步骤 运行安装程序: 双击下载的.exe安装文件 如果出现安全提示&…...
NLP学习路线图(二十三):长短期记忆网络(LSTM)
在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...
Rapidio门铃消息FIFO溢出机制
关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系,以下是深入解析: 门铃FIFO溢出的本质 在RapidIO系统中,门铃消息FIFO是硬件控制器内部的缓冲区,用于临时存储接收到的门铃消息(Doorbell Message)。…...
重启Eureka集群中的节点,对已经注册的服务有什么影响
先看答案,如果正确地操作,重启Eureka集群中的节点,对已经注册的服务影响非常小,甚至可以做到无感知。 但如果操作不当,可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...
Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...
CSS | transition 和 transform的用处和区别
省流总结: transform用于变换/变形,transition是动画控制器 transform 用来对元素进行变形,常见的操作如下,它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么?它的作用是什么? Spring框架的核心容器是IoC(控制反转)容器。它的主要作用是管理对…...
