当前位置: 首页 > news >正文

Lua学习笔记:require非.lua拓展名的文件

前言
本篇在讲什么

Lua的require相关的内容
本篇需要什么

Lua语法有简单认知
C++语法有简单认知
依赖Visual Studio工具

本篇的特色

具有全流程的图文教学
重实践,轻理论,快速上手
提供全流程的源码内容


★提高阅读体验★

👉 ♠ 一级标题 👈

👉 ♥ 二级标题 👈

👉 ♣ 三级标题 👈

👉 ♦ 四级标题 👈

目录

  • ♠ 前言
  • ♠ 前瞻
  • ♠ require的定义
  • ♠ Lua的加载器
  • ♠ 简单的断点调试
  • ♠ require自定义文件
    • ♥ 修改Lua_Path
  • ♠ 自定义加载器
    • ♥ 自定义
  • ♠ 推送
  • ♠ 结语


♠ 前言

想在Lua代码中去require非.lua后缀的文件,发现需要去自定义一下Lua的加载器,这里我们先从c源码的角度去探究一下require的过程,再自定义一个加载器去加载指定后缀的Lua代码文件


♠ 前瞻

阅读本篇文章需要准备编译Lua源码的工程,详情可参考下面文章

Lua学习笔记:在Visual Studio中调试Lua源码和打断点

阅读本篇文章前最好提前了解C/C++和Lua的交互原理,详情可参考下面文章

Lua学习笔记:C/C++和Lua的相互调用

阅读本篇文章前最好提前了解Lua的package,详情可参考下面文章

Lua学习笔记:探究package

阅读本篇文章前最好提前了解Lua的词法分析,详情可参考下面文章

Lua学习笔记:词法分析


♠ require的定义

require的本质其实是注册在_G内的一个全局函数,在Lua中如果把_G去dump一下,可以看到方法名字在其中

在这里插入图片描述

原型函数定义在源码loadlib.c中,名为ll_require的函数,其在luaopen_package函数中被注册到全局表当中

在这里插入图片描述


♠ Lua的加载器

在Lua初始化的时候定义了几个默认加载器去读取文件内容,在loadlib.c文件中的luaopen_package方法中去初始化了加载器

在这里插入图片描述

其中loader_lua就是用来加载Lua文件的默认加载器,只要是require一个lua文件就默认会执行

在这里插入图片描述


♠ 简单的断点调试

我们预先准备了两个Lua文件,加几个断点来看一下执行流程,Lua代码如下所示

在这里插入图片描述

我们分别在ll_requireloader_Lua函数中添加了断点,在执行后,依次执行了两个函数,最终在luaL_loadfile函数中完成对require文件的词法分析

在这里插入图片描述

在这里插入图片描述


♠ require自定义文件

默认的对Lua的读取只支持.lua后缀的文件,我们可以通过几种不同的方式去改变这一策略


♥ 修改Lua_Path

Lua的package表中字段path留存的就是文件的搜索路径,我们可以通过补充搜索路径来达到目的

在这里插入图片描述

可以直接通过修改源码中的LUA_PATH_DEFAULT定义,去使得Lua程序可以加载.luac结尾的文件,执行后可直接被require

在这里插入图片描述

源码可能并不是能随便修改的,我们也可以直接在Lua代码中为package.path添加搜索路径,如下图所示

在这里插入图片描述


♠ 自定义加载器

如果require的文件后缀不是.lua在require的时候会报错,原因是在默认加载器loader_Lua并没有设定对其他后缀的加载方式,不过我们可以自定义加载器

在这里插入图片描述

在这里插入图片描述


♥ 自定义

如下述代码所示,在执行脚本加载之前,将loaders的默认加载器替换成我们自定义的函数就可以了

int myLuaLoader(lua_State * L)
{std::string filename(luaL_checkstring(L, 1));return 1;
}void addLuaLoader(lua_State * _state, lua_CFunction func)
{if (!func) return;lua_getglobal(_state, "package");                                  /* L: package */lua_getfield(_state, -1, "loaders");                               /* L: package, loaders */lua_pushcfunction(_state, func);                                   /* L: package, loaders, func */for (int i = (int)(lua_objlen(_state, -2) + 1); i > 2; --i){lua_rawgeti(_state, -2, i - 1);                                /* L: package, loaders, func, function */lua_rawseti(_state, -3, i);                                    /* L: package, loaders, func */}lua_rawseti(_state, -2, 2);                                        /* L: package, loaders */lua_setfield(_state, -2, "loaders");                               /* L: package */lua_pop(_state, 1);}int main()
{lua_State* L = luaL_newstate();luaL_openlibs(L);addLuaLoader(L, myLuaLoader);luaL_dofile(L, "lua_src/test.lua");lua_close(L);
}

我们在myLuaLoader函数中加入断点,在执行程序后已经可以获取到对应的文件名字了

在这里插入图片描述

接下来,我们补充函数内容,让其可以去识别到特定后缀的文件,很简单,直接拼接.luac结尾后缀,然后去loadfile,大家可以根据自己需求去扩展

int myLuaLoader(lua_State * L)
{const char *filePath = "D:\\work\\cToLua\\Debug_Lua\\";const char *name = luaL_checkstring(L, 1);const char *suffix = ".luac";char *filename = (char *)malloc(strlen(filePath) + strlen(name)+ strlen(suffix));sprintf(filename, "%s%s%s", filePath, name, suffix);if (luaL_loadfile(L, filename) != 0)return 0;return 1;
}

♠ 推送

  • Github
https://github.com/KingSun5

♠ 结语

若是觉得博主的文章写的不错,不妨关注一下博主,点赞一下博文,另博主能力有限,若文中有出现什么错误的地方,欢迎各位评论指摘。

👉 本文属于原创文章,转载请评论留言,并在转载文章头部著名作者出处👈

相关文章:

Lua学习笔记:require非.lua拓展名的文件

前言 本篇在讲什么 Lua的require相关的内容 本篇需要什么 对Lua语法有简单认知 对C语法有简单认知 依赖Visual Studio工具 本篇的特色 具有全流程的图文教学 重实践,轻理论,快速上手 提供全流程的源码内容 ★提高阅读体验★ 👉 ♠…...

Python 编程基础 | 第三章-数据类型 | 3.3、浮点数

一、浮点数...

beego---ORM相关操作

Beego框架是go语言开发的web框架。 **那什么是框架呢?**就是别人写好的代码,我们可以直接使用!这个代码是专门针对某一个开发方向定制的,例如:我们要做一个网站,利用 beego 框架就能非常快的完成网站的开发…...

【网络原理】初始网络,了解概念

文章目录 1. 网络通信1.1 局域网LAN1.2 广域网WAN 2. 基础概念2.1 IP2.2 端口号 3. 认识协议4. 五元组5. 协议分层5.1 分层的作用5.2 OSI七层模型5.3 TCP/IP五层(四层)模型 6. 封装和分用 1. 网络通信 计算机与计算机之间是互相独立,是独立模…...

对象存储,从单机到分布式的演进

关于数据存储的相关知识,请大家关注“数据存储张”,各大平台同名。 通过《什么是云存储?从对象存储说起》我们对对象存储的历史、概念和基本使用有了一个大概的认识。而且我们以Minio为例,通过单机部署的模式实际操作了一下对象存储的GUI,感受了一下对象存储的用法。 在上…...

结构型设计模式——桥接模式

摘要 桥接模式(Bridge pattern): 使用桥接模式通过将实现和抽象放在两个不同的类层次中而使它们可以独立改变。 一、桥接模式的意图 将抽象与实现分离开来,使它们可以独立变化。 二、桥接模式的类图 Abstraction: 定义抽象类的接口Implementor: 定义实现类接口 …...

keepalived的vip实现nginx节点的主备

nginx wget http://nginx.org/download/nginx-1.18.0.tar.gz tar zxvf nginx-1.18.0.tar.gzyum install -y gcc gcc-c pcre pcre-devel zlib zlib-devel openssl openssl-devel libnl3-develcd nginx-1.18.0 mkdir -p /usr/local/nginx #需要使用https,在编译时启用…...

C++之std::atomic解决多线程7个问题(二百四)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生…...

tailwindcss 如何在 uniapp 中使用

直接使用https://tailwindcss.com/docs/guides/vite这篇官方教程的写法是跑不通的,摸索以后整理了一下,最关键的是第6步 npm install -D tailwindcss postcss autoprefixernpx tailwindcss init -p在 tailwind.config.js 中写入 export default {conten…...

oracle-使用PLSQL工具自行修改用户密码

1、使用PLSQL工具,输入用户名和原密码登录,如下图 2、登录后,在会话下拉菜单中找到”Change password..” 3、在跳出的窗口中配置新密码,修改完成后单击”确认”,后退出PLSQL 4、重新打开PLSQL,使用新密码登…...

自动驾驶技术:现状与未来

自动驾驶技术:现状与未来 文章目录 引言自动驾驶技术的现状自动驾驶技术的挑战自动驾驶技术的未来结论结论 2023星火培训【专项营】Apollo开发者社区布道师倾力打造,包含PnC、新感知等的全新专项课程上线了。理论与实践相结合,全新的PnC培训不…...

C++ 类构造函数 析构函数

类的构造函数 类的构造函数是类的一种特殊的成员函数,它会在每次创建类的新对象时执行。 构造函数的名称与类的名称是完全相同的,并且不会返回任何类型,也不会返回 void。构造函数可用于为某些成员变量设置初始值。 下面的实例有助于更好地…...

C++标准模板(STL)- 输入/输出操纵符-(std::get_time,std::put_time)

操纵符是令代码能以 operator<< 或 operator>> 控制输入/输出流的帮助函数。 不以参数调用的操纵符&#xff08;例如 std::cout << std::boolalpha; 或 std::cin >> std::hex; &#xff09;实现为接受到流的引用为其唯一参数的函数。 basic_ostream::…...

蓝桥等考Python组别九级004

第一部分:选择题 1、Python L9 (15分) 运行下面程序,可以输出几行“*”?( ) for i in range(3): for j in range(4): print(*, end = ) print() 2345正确答案:B 2、Python L9...

gitee 远程仓库操作基础(二)

(1&#xff09;clone远端仓库,本地建立分支推送 (基于远程仓库版本库 本地建立分支开发新功能) git clone gitgitee.com:xxxxx/alsa_test.git git remote add origin gitgitee.com:xxxxx/alsa_test.git进入clone过后路径代码,查看本地分支,发现该项目远程仓库有很多分支 基于…...

Scala第四章节

Scala第四章节 scala总目录 章节目标 掌握分支结构的格式和用法掌握for循环和while循环的格式和用法掌握控制跳转语句的用法掌握循环案例理解do.while循环的格式和用法 1. 流程控制结构 1.1 概述 在实际开发中, 我们要编写成千上万行代码, 代码的顺序不同, 执行结果肯定也…...

【C++入门指南】类和对象(上)

【C杂货店】类和对象&#xff08;上&#xff09; 一、面向过程和面向对象初步认识二、类的引入三、类的定义四、类的访问限定符及封装4.1 访问限定符4.2 封装 五、类的作用域六、类的实例化七、类对象模型7.1 类对象的存储规则7.2 例题7.3结构体内存对齐规则 八、this指针8.2 t…...

web:[极客大挑战 2019]PHP

题目 点进页面显示如下 根据页面提示&#xff0c;这个网站有备份文件&#xff0c;备份文件一般是bak文件格式&#xff0c;用dirsearch扫描 访问之后下载了一个文件 里面都是一些代码 在index.php中发现了一个类的文件&#xff0c;一个get传参&#xff0c;然后将传进的值进行反序…...

Firefox 开发团队对 Vue 3 进行优化效果显著

Mozilla 官方博客近日发表文章《Faster Vue.js Execution in Firefox》&#xff0c;介绍了 Firefox 开发团队对 Vue 3 进行的优化。 文章写道&#xff0c;在使用 Speedometer 3 对 Firefox 进行基准测试时&#xff0c;他们发现 Vue.js test 的测试结果从 Vue 2 升级到 Vue 3 后…...

【Verilog 教程】6.5 Verilog避免Latch

关键词&#xff1a;触发器&#xff0c;锁存器 Latch 的含义 锁存器&#xff08;Latch&#xff09;&#xff0c;是电平触发的存储单元&#xff0c;数据存储的动作取决于输入时钟&#xff08;或者使能&#xff09;信号的电平值。仅当锁存器处于使能状态时&#xff0c;输出才会随着…...

怒刷LeetCode的第21天(Java版)

目录 第一题 题目来源 题目内容 解决方法 方法一&#xff1a;哈希表 方法二&#xff1a;计数器数组 第二题 题目来源 题目内容 解决方法 方法一&#xff1a;分治法 方法二&#xff1a;快速幂 迭代 方法三&#xff1a;快速幂 递归 第三题 题目来源 题目内容 …...

Armv9 Cortex-A720的L2 memory system 和 L2 Cache

9 L2 memory system Cortex-A720核心的L2内存系统通过CPU bridge连接core与DynamIQ Shared Unit-120,其中包括私有的L2缓存。 L2缓存是统一的,每个Cortex-A720核心在一个集群中都有私有的L2缓存。 L2内存系统包括使用虚拟地址(VA)和程序计数器(PC)的数据预取引擎。不同…...

蓝桥等考Python组别九级003

第一部分:选择题 1、Python L9 (15分) 运行下面程序,可以输出几行“*”?( ) for i in range(3): for j in range(4): print(*, end = ) print() 6374正确答案:B 2、Python L9...

Python异步框架大战:FastAPI、Sanic、Tornado VS Go 的 Gin

一、前言 异步编程在构建高性能 Web 应用中起着关键作用&#xff0c;而 FastAPI、Sanic、Tornado 都声称具有卓越的性能。本文将通过性能压测对这些框架与Go的Gin框架进行全面对比&#xff0c;揭示它们之间的差异。 原文&#xff1a;Python异步框架大战&#xff1a;FastAPI、Sa…...

Docker笔记1

一、Docker介绍 Docker是一个开源的应用容器引擎&#xff0c;基于Go语言并遵从Apache2.0协议开源 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中&#xff0c;然后发布到任何流行的Linux机器上&#xff0c;也可以实现虚拟化。 容器是完全使用沙箱机制&a…...

TensorFlow-Federated简介与安装

1、简介 TensorFlow Federated&#xff08;TFF&#xff09;是一个用于机器学习和其他分布式数据计算的开源框架。TFF 的开发旨在促进联邦学习 &#xff08;FL&#xff09;的开放研究和实验。联邦学习是一种机器学习方法&#xff0c;其中一个共享的全局模型在许多参与的客户之间…...

【强化学习】基础概念

1. Agent (智能体) 智能体是进行决策和学习的实体&#xff0c;它能感知环境的状态&#xff0c;并基于策略采取动作以影响环境。智能体的目标是通过与环境的交互获得最大化的累积奖励。 2. Environment (环境) 环境是智能体所处的外部系统&#xff0c;它与智能体交互。环境的…...

云原生Kubernetes:K8S集群各组件服务重启

目录 一、理论 1.各组件服务重启命令 一、理论 1.各组件服务重启命令 &#xff08;1&#xff09;Master节点Node节点共同服务 systemctl restart etcd systemctl daemon-reload systemctl enable flanneld systemctl restart flanneld &#xff08;2&#xff09;Master节…...

闲话Python编程-循环

1. for循环 Python的for语句有点特别&#xff0c;只能对序列和字符串进行处理&#xff0c;序列自然包括list、tuple和range对象。 #!/usr/bin/env python3 # -*- coding: utf-8 -*- # 练习for语句def loop_for():names [Tom, Jack, Black]for name in names:print(name)s ab…...

建筑能源管理(3)——建筑能源监管

为了全面落实科学发展观&#xff0c;提高建筑能源管理水平&#xff0c;进一步降低能源和水资源消耗、合理利用资源&#xff0c;以政府办公建筑和大型公共建筑的运行节能管理为突破口&#xff0c;建立了既有政府办公建筑和大型公共建筑运行节能监管体系&#xff0c;旨在提高政府…...

python如何安装wordpress/手机百度app安装下载

在做web项目开发中&#xff0c;尤其是企业级应用开发的时候&#xff0c;往往会在工程启动的时候做许多的前置检查或者去执行某些方法。而在Spring的web项目中&#xff0c;可以介入Spring的启动过程。在Spring容器将所有的Bean都初始化完成之后&#xff0c;做一些操作&#xff0…...

wordpress 主页布局/nba赛季排名

RCF的使用教程 RCF(Remote Call Framework)是一个使用C编写的RPC框架&#xff0c;在底层RCF支持多种传输实现方式(transport implementations). 包括TCP&#xff0c;UDP&#xff0c;多播&#xff0c;组播&#xff0c;win32命名管道和unix domain socket。下面我以一个例子讲述…...

成都网站设计新闻/百度关键词排名批量查询工具

1 发请求的各种方法 使用form标签&#xff08;会在当前页面刷新或者新开一个页面刷新&#xff09; <form action"" methodpost/get><input type"submit"></form> 使用a标签&#xff08;会在当前页面刷新或者新开一个页面刷新&#xff…...

站点创建/中国十大关键词

PostgreSQL中生成列是从其他列计算而来的特殊列。生成列与普通列不同&#xff0c;不是固定的值&#xff0c;而是又引用表中其他列的表达式决定的。生成列在SQL标准&#xff08;ISO/IEC 9075&#xff09;中引入&#xff0c;被主流RDBMS支持&#xff0c;PostgreSQL12开始支持生成…...

国外网站推荐/常州seo外包

哈工大威海数据结构实验一 线性结构 一元多项式的求导 直接放代码 #include <iostream> using namespace std; typedef struct Function{int coef ;int index ;struct Function * next;}Data ; class List{ public:Data* CreatData(int coef,int index){Data * head;h…...

怎么做网赌网站/网络营销的方式和方法

前言 Javascript是一门基于对象的动态语言&#xff0c;也就是说&#xff0c;所有东西都是对象&#xff0c;一个很典型的例子就是函数也被视为普通的对象。Javascript可以通过一定的设计模式来实现面向对象的编程&#xff0c;其中this “指针”就是实现面向对象的一个很重…...