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

这篇具有很好参考价值的文章主要介绍了Lua学习笔记:require非.lua拓展名的文件。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言
本篇在讲什么

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

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

本篇的特色

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

lua require文件,lua学习笔记,lua,学习,笔记
★提高阅读体验★

👉 ♠ 一级标题 👈

👉 ♥ 二级标题 👈

👉 ♣ 三级标题 👈

👉 ♦ 四级标题 👈


♠ 前言

想在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一下,可以看到方法名字在其中

lua require文件,lua学习笔记,lua,学习,笔记

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

lua require文件,lua学习笔记,lua,学习,笔记


♠ Lua的加载器

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

lua require文件,lua学习笔记,lua,学习,笔记

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

lua require文件,lua学习笔记,lua,学习,笔记


♠ 简单的断点调试

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

lua require文件,lua学习笔记,lua,学习,笔记

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

lua require文件,lua学习笔记,lua,学习,笔记

lua require文件,lua学习笔记,lua,学习,笔记


♠ require自定义文件

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


♥ 修改Lua_Path

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

lua require文件,lua学习笔记,lua,学习,笔记

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

lua require文件,lua学习笔记,lua,学习,笔记

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

lua require文件,lua学习笔记,lua,学习,笔记


♠ 自定义加载器

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

lua require文件,lua学习笔记,lua,学习,笔记

lua require文件,lua学习笔记,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函数中加入断点,在执行程序后已经可以获取到对应的文件名字了

lua require文件,lua学习笔记,lua,学习,笔记

接下来,我们补充函数内容,让其可以去识别到特定后缀的文件,很简单,直接拼接.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

♠ 结语

若是觉得博主的文章写的不错,不妨关注一下博主,点赞一下博文,另博主能力有限,若文中有出现什么错误的地方,欢迎各位评论指摘。文章来源地址https://www.toymoban.com/news/detail-730369.html

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

到了这里,关于Lua学习笔记:require非.lua拓展名的文件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Lua学习笔记】Lua进阶——Table,迭代器

    在【Lua学习笔记】Lua入门中我们讲到了Lua的一些入门知识点,本文将补充Lua的一些进阶知识 在上篇文章的最后,我们指出通过查询_G的字符索引,发现table.insert实际上是一个名为table的table结构里的索引指向的函数 实际上不仅它,所有的函数,模块,全局变量,元表 😅😅😅

    2024年02月15日
    浏览(28)
  • 【Lua学习笔记】Lua进阶——Table(3) 元表

    接上文 Q:为什么要使用元表? A:在Lua中,常常会需要表与表之间的操作。元表中提供了一些元方法,通过自定义元方法可以实现想要的功能,相当于面向对象中给你一系列方法让你重载。 使用下列代码设置元表: 通常在元表中操作分为三步: 操作子表 检测是否有元表 若

    2024年02月15日
    浏览(25)
  • lua学习笔记21完结篇(lua中的垃圾回收)

    输出 学习地址  【唐老狮】Unity热更新之Lua语法_哔哩哔哩_bilibili 

    2024年04月15日
    浏览(39)
  • 【Lua学习笔记】Lua进阶——Table(4)继承,封装,多态

    现在我们可以像面向对象一样,new一个对应基类的对象了。但是这里的new也不完全相似与面向对象的new,例如我们可以这样做: 我们在封装Object类的时候可完全没有name这个索引,而在Lua中我们new了一个新对象,还能新加入一些变量和方法,这些特性明显是继承了父类的子类才

    2024年02月15日
    浏览(36)
  • lua学习笔记

    单行注释: 多行注释: 命名: Lua不支持下划线+大写字母,比如:_ABC 但支持:_abc : 全局变量: 直接变量名 = 内容就是全局 局部变量: 加上local即可 nil: nil是空的意思,即什么也没有 lua的数据类型: table: lua从下表为1开始的 if else elseif: nil默认为false ..: ..为字

    2024年02月07日
    浏览(34)
  • lua语法学习笔记(速成版)

    使用官方的浏览器测试网站进行代码测试。wiki.loatos.com 创建变量 类似python,直接赋值即生成全局变量; 加 local 变成 仅本文件使用变量; 数据类型 nul和number 未被声明(或叫创建)的值都是 nul,类似NULL。 number 数值型,支持16进制表示法和科学计数法。 字符串 单引号

    2024年02月05日
    浏览(39)
  • lua脚本语言学习笔记

    Lua 是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。 因为我们使用redis的时候一般要写lua脚本,这篇文章就介绍一下lua脚本语言的基础用法。 window操作系统下可以使用SciTE来

    2024年02月16日
    浏览(39)
  • Lua学习笔记:面向对象的实现

    前言 本篇在讲什么 Lua中的面向对象的实现 本篇适合什么 适合 初学Lua 的小白 本篇需要什么 对 Lua 语法有简单认知 依赖 Sublime Text 编辑器 本篇的特色 具有全流程的 图文教学 重实践,轻理论,快速上手 提供全流程的 源码 内容 ★提高阅读体验★ 👉 ♣ 三级标题 👈 👉 ♦

    2024年02月13日
    浏览(35)
  • Lua学习笔记:浅谈table的实现

    前言 本篇在讲什么 Lua中的table的实现 本篇适合什么 适合 初学Lua 的小白 本篇需要什么 对 Lua 语法有简单认知 依赖 Sublime Text 编辑器 本篇的特色 具有全流程的 图文教学 重实践,轻理论,快速上手 提供全流程的 源码 内容 ★提高阅读体验★ 👉 ♣ 三级标题 👈 👉 ♦ 四级标

    2024年02月12日
    浏览(30)
  • lua学习笔记18(面相对象之多态)

    输出  

    2024年04月13日
    浏览(25)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包