Lua学习笔记:探究package

前言
本篇在讲什么

理解Lua的package
本篇需要什么

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

本篇的特色

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


★提高阅读体验★

👉 ♠ 一级标题 👈

👉 ♥ 二级标题 👈

👉 ♣ 三级标题 👈

👉 ♦ 四级标题 👈

目录

  • ♠ 前言
  • ♠ 前瞻
  • ♠ 注册标准库
    • ♥ luaL_openlibs
    • ♥ luaopen_package
  • ♠ package的参数
    • ♥ loaders
    • ♥ cpath
    • ♥ path
    • ♥ loaded
    • ♥ loadlib
    • ♥ seeall
  • ♠ 推送
  • ♠ 结语


♠ 前言

本篇文章简单了解一下Lua的全局表package,及其表内字段功能


♠ 前瞻

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

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

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

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


♠ 注册标准库

首先我们要知道,在创建一个新的Lua虚拟机后,其环境内是没有定义任何函数的,我们需要注册一下标准库以供使用,代码如下

lua_State* L = luaL_newstate();
luaL_openlibs(L);

我们通过函数luaL_openlibs向Lua环境注册一些标准函数


♥ luaL_openlibs

函数原型在在脚本linit.c当中,代码如下所示

static const luaL_Reg lualibs[] = {{"", luaopen_base},{LUA_LOADLIBNAME, luaopen_package},{LUA_TABLIBNAME, luaopen_table},{LUA_IOLIBNAME, luaopen_io},{LUA_OSLIBNAME, luaopen_os},{LUA_STRLIBNAME, luaopen_string},{LUA_MATHLIBNAME, luaopen_math},{LUA_DBLIBNAME, luaopen_debug},{NULL, NULL}
};LUALIB_API void luaL_openlibs (lua_State *L) {const luaL_Reg *lib = lualibs;for (; lib->func; lib++) {lua_pushcfunction(L, lib->func);lua_pushstring(L, lib->name);lua_call(L, 1, 0);}
}

可以看到在for循环当中以此把lualibs数组内的函数和函数名字注册到了lua_State


♥ luaopen_package

函数luaopen_package是注册package表的核心函数,其源码定义在脚本loadlib.c当中,如下所示

LUALIB_API int luaopen_package (lua_State *L) {int i;/* create new type _LOADLIB */luaL_newmetatable(L, "_LOADLIB");lua_pushcfunction(L, gctm);lua_setfield(L, -2, "__gc");/* create `package' table */luaL_register(L, LUA_LOADLIBNAME, pk_funcs);
#if defined(LUA_COMPAT_LOADLIB) lua_getfield(L, -1, "loadlib");lua_setfield(L, LUA_GLOBALSINDEX, "loadlib");
#endiflua_pushvalue(L, -1);lua_replace(L, LUA_ENVIRONINDEX);/* create `loaders' table */lua_createtable(L, 0, sizeof(loaders)/sizeof(loaders[0]) - 1);/* fill it with pre-defined loaders */for (i=0; loaders[i] != NULL; i++) {lua_pushcfunction(L, loaders[i]);lua_rawseti(L, -2, i+1);}lua_setfield(L, -2, "loaders");  /* put it in field `loaders' */setpath(L, "path", LUA_PATH, LUA_PATH_DEFAULT);  /* set field `path' */setpath(L, "cpath", LUA_CPATH, LUA_CPATH_DEFAULT); /* set field `cpath' *//* store config information */lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATHSEP "\n" LUA_PATH_MARK "\n"LUA_EXECDIR "\n" LUA_IGMARK);lua_setfield(L, -2, "config");/* set field `loaded' */luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 2);lua_setfield(L, -2, "loaded");/* set field `preload' */lua_newtable(L);lua_setfield(L, -2, "preload");lua_pushvalue(L, LUA_GLOBALSINDEX);luaL_register(L, NULL, ll_funcs);  /* open lib into global table */lua_pop(L, 1);return 1;  /* return 'package' table */
}

我们挑重点来看,在开始向环境当中注册了一个名为package的表,并且在表中注册了两个名为loadlibseeall的函数

static const luaL_Reg pk_funcs[] = {{"loadlib", ll_loadlib},{"seeall", ll_seeall},{NULL, NULL}
};/* create `package' table */
luaL_register(L, LUA_LOADLIBNAME, pk_funcs);

随后依次为表package设置了loaders、path、cpath、config、loaded、preload参数

lua_setfield(L, -2, "loaders");  /* put it in field `loaders' */
setpath(L, "path", LUA_PATH, LUA_PATH_DEFAULT);  /* set field `path' */
setpath(L, "cpath", LUA_CPATH, LUA_CPATH_DEFAULT); /* set field `cpath' */
lua_setfield(L, -2, "config");
lua_setfield(L, -2, "loaded");
lua_setfield(L, -2, "preload");

最后又向loaded中的全局表_G中注册了两个名为requiremodule的函数

static const luaL_Reg ll_funcs[] = {{"module", ll_module},{"require", ll_require},{NULL, NULL}
};lua_pushvalue(L, LUA_GLOBALSINDEX);
luaL_register(L, NULL, ll_funcs);  /* open lib into global table */

所以经过了上述一通操作,我们的全局表package最终变成了下面这个样子

{["config"]   = "...",["cpath"]    = "...",["loaded"]   = {["_G"]   = {["require"] = function,["module"]  = function,}},["loaders"]  = {},["loadlib"]  = function,["path"]     = "...",["preload"]  = {},["seeall"]   = function,
}

♠ package的参数

从上边创建package的时候我们其实已经知道,其中所包含的字段,这里我们简单了解一下这些个字段都是干嘛用的

通过pairs遍历package的key值,也可以很直观的看到package中所有的参数

在这里插入图片描述


♥ loaders

存储加载器的表,打印出来如下图所示

在这里插入图片描述

其对应的四个加载器,定义在loadlib.c中,代码如下图所示

static const lua_CFunction loaders[] ={loader_preload, loader_Lua, loader_C, loader_Croot, NULL};

这个加载器可以理解为解析文件的方式,比如我们require了一个lua文件,那么会通过loader_Lua方法去解析文件,如果require了一个c文件,那么会通过loader_C方法去解析文件

后续得空专门为require的流程再写一遍笔记


♥ cpath

c加载器的搜索路径,loader_C方法会从package.cpath路径下搜索对应的文件

在这里插入图片描述


♥ path

Lua文件加载器的搜索路径,Luader_Lua方法会从package.path下搜索对应的Lua文件

在这里插入图片描述

在这里插入图片描述

我们在D盘某个路径下有个lua文件test3.lua,我们从c盘的一个lua文件正常是require不到他的,现在只要补充搜索路径即可,如下所示

package.path = package.path .. ";D:\\lua_src\\?.lua"
require "test3"

♥ loaded

管理全局函数和已经加载的标准库,在loaded内存在表__G,全局函数和全局表都会存其中管理

在这里插入图片描述

管理一些已经require的模块,require的时候首先会判断package.loaded内是否已经加载过了,如果加载过了直接返回

在这里插入图片描述


♥ loadlib

加载c库中的方法,返回的是一个lua_CFunction,只加载不执行


♥ seeall

为模块设置一个元表,其__index字段引用_G,以便该模块继承全局环境的值。作为功能模块的选项,功能等同于下面代码

setmetatable(M, {__index = _G});

♠ 推送

  • Github
https://github.com/KingSun5

♠ 结语

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

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

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

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

相关文章

ruoyi框架修改左侧菜单样式

菜单效果 ruoyi前端框架左侧的菜单很丑,我们需要修改一下样式,下面直接看效果。 修改代码 1、sidebar.scss .el-menu-item, .el-submenu__title {overflow: hidden !important;text-overflow: ellipsis !important;white-space: nowrap !important;//…

微软宣布推广数字助理 Copilot;GPT 应用开发和思考

🦉 AI新闻 🚀 微软宣布推广基于生成式人工智能的数字助理 Copilot 摘要:微软宣布将基于生成式人工智能的数字助理 Copilot 推广到更多软件产品中。新的 AI 助理 Microsoft Copilot 将在 Windows 中无缝可用,包括 Windows 11 桌面…

【C++面向对象侯捷】12.虚函数与多态 | 13.委托相关设计【设计模式 经典做法,类与类之间关联起来,太妙了,不断的想,不断的写代码】

文章目录 12.虚函数与多态举例:委托 继承【观察者模式】13.委托相关设计Composite 组合模式Prototype 原型模式 12.虚函数与多态 纯虚函数 一定要 子类重新定义的 继承和复合 关系下的构造和析构 举例:委托 继承【观察者模式】 13.委托相关设计 问题…

BOM与DOM--记录

BOM基础(BOM简介、常见事件、定时器、this指向) BOM和DOM的区别和联系 JavaScript的DOM与BOM的区别与用法详解 DOM和BOM是什么?有什么作用? 图解BOM与DOM的区别与联系 BOM和DOM详解 JavaScript 中的 BOM(浏览器对…

蓝桥杯 题库 简单 每日十题 day8

01 扫雷 题目描述 在一个n行列的方格图上有一些位置有地雷,另外一些位置为空。 请为每个空位置标一个整数,表示周围八个相邻的方格中有多少个地雷。 输入描述 输入的第一行包含两个整数n,m。 第2行到第n1行每行包含m个整数,相邻整…

数据结构——单链表

目录 一.前言 二.链表表示和实现(单链表) 1.1 顺序表的优缺点 1.2 链表的概念及结构 1.3 打印函数 1.4 空间函数 1.5 尾插函数(最最最麻烦的) 1.5.1 尾插最关键部分! 1.6 头插函数 1.7 尾删函数…

深拷贝和浅拷贝

两者区别 深拷贝和浅拷贝是用来描述对象或者对象数组这种引用数据类型的复制场景的。 浅拷贝 浅拷贝,就是只复制某个对象的指针,而不复制对象本身。这种复制方式意味着两个引用指针指向被复制对象的同一块内存地址,如下图: 深拷贝…

conda的安装和使用

参考资料: https://www.bilibili.com/read/cv8956636/?spm_id_from333.999.0.0 https://www.bilibili.com/video/BV1Mv411x775/?spm_id_from333.999.0.0&vd_source98d31d5c9db8c0021988f2c2c25a9620 目录 conda是啥以及作用conda的安装conda的启动conda的配置…

git和github的入门操作

之前因为工作中用的都是SVN版本控制工具,没接触过git和github,现在开始深入自学Django框架技术后,看到官网推荐使用git,然后这两天网上查阅了很多文章教程,学到入门操作需要学习的点,太多的知识点要后面慢慢…

多输入多输出 | MATLAB实现GA-BP遗传算法优化BP神经网络多输入多输出

多输入多输出 | MATLAB实现GA-BP遗传算法优化BP神经网络多输入多输出 目录 多输入多输出 | MATLAB实现GA-BP遗传算法优化BP神经网络多输入多输出预测效果基本介绍程序设计往期精彩参考资料 预测效果 基本介绍 多输入多输出 | MATLAB实现GA-BP遗传算法优化BP神经网络多输入多输出…

接入国家能源平台MQTT应用案例

一、项目介绍 随着国家对节能环保措施的力度不断加大,基于物联网技术搭建的国家能源平台在国家相关部门的建设下逐渐成熟。致力于利用实际能耗数据建立能效仿真模型,通过实时寻优运算,获得当前的最优化运行策略,并将控制指令下发…

MDK工程转换Vscode+EIDE方法

MDK工程转换VscodeEIDE方法 1、VscodeEIDE环境搭建方法 请按下方视频完成环境搭建,并编译成功。下载,单步调试如无视频中芯片可暂不执行。 https://www.bilibili.com/video/BV1Zu4y1f72H/?spm_id_from333.337.search-card.all.click&vd_source73…

摩尔信使MThings实用功能盘点

“冗长的用户手册”与“精简的交互设计”之间势必产生一条信息鸿沟,现在就来盘点一下摩尔信使MThings有哪些隐蔽而实用的功能。 01 数据配置类 一键刷新 功能:快速读取所有位数据、寄存器数据的当前数值。 操作:双击“数值”列表头。 一键…

有一个新工具,能让程序员变成高手,优雅撸它!

不知道从什么时候开始,程序员这个职位变得家喻户晓,对程序员的印象也从以前的高深莫测变成如今的加班代名词。对于程序员加班,不懂有话要说。 作为大厂的一枚螺丝钉,接到任务的第一时间需要缕清底层逻辑,并随时关注部门…

AUTOSAR实战篇:手把手带你搞定Watchdog协议栈

AUTOSAR实战篇:手把手带你搞定Watchdog协议栈 前言 小T出品,必是精品! 手把手搞定Watchdog协议栈,你值得拥有! 正文 在进行Watchdog协议栈实战之前,建议先阅读小T之前有关Watchdog协议栈的两篇文章《Watchdog协议栈上》与《Watchdog协议栈下》先了解下在AUTOSAR框架下的W…

SQL模板-用户留存率计算

在这段实习中,我遇到了用户留存率计算的需求,这里做个总结。 首先来讲下,什么是用户留存? 在互联网行业中,用户在某段时间内开始使用应用,经过一段时间后,仍然继续使用该应用的用户。用户留存一…

【数据分享】2005-2022年全国民航机场客货吞吐量和起降架次数据

机场是一个城市对外联系的重要渠道,机场的旅客吞吐量和货物吞吐量是体现一个城市对外联系程度的重要指标。 本次我们给大家分享的是2005-2022年我国民航机场的旅客吞吐量、货邮吞吐量、起降架次数据。数据格式为Excel和Shp两种格式。数据坐标为WGS1984。原始数据来…

根据条件关闭软件

使用下载工具时,经常出现磁盘空间已满,无法下载的情况。 使用shell写一个监控,每2分钟执行一次。判断当前磁盘的空间,低于2G时,关闭下载软件。 获取空间大小 ➜ ~ df -h …

CTF--攻防世界杂项--第二课

下载题目根据文件类型可知,这是一个流量包 那么接下来就是利用分析流量包常用的工具wireshark来分析 利用关键词进行搜索 http contains shell 在最后一条数据中看到了flag。 以上就结束,非常简单的一道题。

使用Visual Leak Detector排查内存泄漏问题

目录 1、VLD工具概述 2、下载、安装VLD 2.1、下载VLD 2.2、安装VLD 3、VLD安装目录及文件说明 3.1、安装目录及文件说明 3.2、关于32位和64位版本的详细说明 4、在工程中引入VLD 5、内存泄漏检测实例讲解 5.1、程序启动报错 5.2、启动调试,查看内存泄漏报…