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

news2025/1/11 18:29:46
前言
本篇在讲什么

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

♠ 结语

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1039455.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ChatGPT的问世给哪些行业带来了冲击?

目录 引言Chat GPT 对行业的影响在线客服和智能客服行业传统自动回复机器人的局限性Chat GPT 的提升能力 教育培训行业个性化学习需求的挑战Chat GPT 的个性化优势 金融保险行业客户服务的变革Chat GPT 的智能化应用 医疗健康领域自助诊断及咨询的便利性Chat GPT 在医疗领域的应…

Spring学习笔记11 GoF代理模式

Spring学习笔记10 JdbcTemplate_biubiubiu0706的博客-CSDN博客 新建个maven模块 static-proxy 演示静态代理 订单接口 测试 需求:统计每个业务方法的耗时 package com.example.proxy.service;/*** author hrui* date 2023/9/25 8:42*/ public class OrderServiceImpl implem…

云安全【阿里云ECS攻防】

关于VPC的概念还请看:记录一下弹性计算云服务的一些词汇概念 - 火线 Zone-安全攻防社区 一、初始化访问 1、元数据 1.1、SSRF导致读取元数据 如果管理员给ECS配置了RAM角色,那么就可以获得临时凭证 如果配置RAM角色 在获取ram临时凭证的时候&#xff…

Android平台轻量级RTSP服务模块如何实现一个服务发布多路RTSP流?

我们在做Android平台轻量级RTSP服务和内网RTSP网关的时候,遇到过这样的问题,如何同时发布多路RTSP流出去? 回答这个问题,实际上不难,大牛直播SDK在设计这个模块的时候,考虑到了一个Service带多路流的情况&…

【Axure高保真原型】滑动评分条_自由控制起始数值

今天和大家分享能自动控制起始数值的滑动评分条的原型模板,我们可以左右拖动滑块或者点击滑条让滑块移动到点击的位置,评分的数值能根据滑块的位置自动计算;我们也可以控制左右侧输入框里的数值,从而控制滑动评分条的区间&#xf…

什么是Peppol ID?如何创建?

Peppol 网络的两大优势是安全和高效,由于Peppol 最常用于电子发票,因此这些优势在电子发票上展露无遗。相比之下,通过电子邮件发送 PDF 格式的发票和其他文件不仅处理成本较高,而且容易出现发票欺诈。 如果您所在的公共部门组织或…

游戏联运和游戏自主运营有什么区别?哪个更好?

游戏联运和游戏自主运营是两种不同的运营模式,各有优劣势,选择取决于具体情况和目标。 一、游戏联运 游戏联运是指将游戏交由第三方发行商或合作伙伴进行运营和推广。这些合作伙伴通常有更丰富的市场经验和资源,能够协助游戏进入不同地区和平…

Linux环境下使用SVN快速访问资料库?试试使用cpolar端口映射

文章目录 前言1. Ubuntu安装SVN服务2. 修改配置文件2.1 修改svnserve.conf文件2.2 修改passwd文件2.3 修改authz文件 3. 启动svn服务4. 内网穿透4.1 安装cpolar内网穿透4.2 创建隧道映射本地端口 5. 测试公网访问6. 配置固定公网TCP端口地址6.1 保留一个固定的公网TCP端口地址6…

LeetCode的第 363 场周赛——记录+补题

研究生生涯第一次打力扣周赛——3题 1. 计算 K 置位下标对应元素的和 class Solution { public:int cnt(int x){int sum 0;while (x) {sum ((x%2)?1:0);x/2;}return sum;}int sumIndicesWithKSetBits(vector<int>& nums, int k) {int n nums.size();int ans 0…

qiankun微服务搭建遇到的坑

目录 1.子应用vue.config中的headers设置成可跨域请求 2.output设置成library&#xff0c;打包成umd库格式 3.父应用使用了babel-pollfill&#xff0c;子应用不要在在bable-pollfill 4.iconfont.js要取消样式隔离才能生效 5.关于nginx的配置 6.主应用和各应用相同依赖的版…

【周赛364-单调栈】美丽塔 II-力扣 2866

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学…

华为OD机试 - 相同数字组成图形的周长 - 矩阵(Java 2023 B卷 100分)

目录 专栏导读一、题目描述二、输入描述三、输出描述四、Java算法源码五、效果展示1、输入2、输出 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷&#xff09;》。 刷的越多…

windows下查看端口及占用端口的进程

1、使用命令查看端口&#xff0c;这里查看10000端口 netstat -aon|findstr "10000" 2、使用tasklist命令查看进程 tasklist|findstr "9640"

基于Spring Boot的在线考试系统springboot19

大家好✌&#xff01;我是CZ淡陌。一名专注以理论为基础实战为主的技术博主&#xff0c;将再这里为大家分享优质的实战项目&#xff0c;本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目&#xff0c;希望你能有所收获&#xff0c;少走一些弯路…

驱动开发:STM32F7控制AD5663模拟量输出

AD5663是ADI公司的一款DAC模块&#xff0c;用以实现两路模拟量信号输出。该芯片通过SPI通信来驱动。下面讲解使用STM32F7主控芯片来控制AD5663模拟量输出的流程。 配置STM32F7 SPI通信管脚 STM32CubeMX生成SPI驱动代码 /* SPI3 init function */ void MX_SPI3_Init(void) {/*…

4年从外包到外企,一个测试老鸟的自述

4年前&#xff0c;我拖着行李箱来到北京&#xff0c;成为了一名北漂&#xff0c;离开了校园的庇护&#xff0c;只身一人&#xff0c;想要在这片陌生的地方闯出一番名堂&#xff0c;可最后却不得人意&#xff0c;面临着所有北漂群体的共同困局&#xff0c;没有归属感&#xff0c…

快速构建开发工具2.0

痛点:使用c开发过程中;尽管CMAKE很强大,方便帮助我们编译好第三方库,但是对第三方库的管理,以及快速搭建开发环境,以及第三方库互相搭配使用并进行demo验证上个人觉得,还是繁琐! 所以写了个小工具,来省略这个过程; 这个工具长这个样子: 他能做什么: 1.只需要勾勾选选,就可以将用…

【Element-UI】Mock.js,案例首页导航、左侧菜单

目录 一、引言 二、Mock.js 1、什么是Mock.js 2、安装配置 2.1、安装 2.2、引入 3、Mock.js的使用 3.1、定义测试数据文件 3.2、mock拦截ajax请求 3.3、模拟测试 三、首页导航、左侧菜单 1、页面搭建 1.1、图标定义 1.2、AppMain.vue 1.3、LeftNav.vue 1.4、To…

​旅行季《乡村振兴战略下传统村落文化旅游设计》许少辉八一论著想象和世界一样宽广

​旅行季《乡村振兴战略下传统村落文化旅游设计》许少辉八一论著想象和世界一样宽广