lua require

环境:

Lua5.1  LuaForWindows

LuaForWindows的下载地址

http://files.luaforge.net/releases/luaforwindows/luaforwindows

 

正题:

require作用类似于C/C++中的#include,其特性为:

1. 根据搜索目录加载指定模块

2. 判定模块是否已加载,避免重复加载

其实现原理:

  对于require加载的模块数据是存储在package.loaded表中,其存储方式以模块名为key,以返回值(模块若无返回值,默认为true)为value进行存储的。比如运行如下程序:

-- package.loaded的类型
print(type(package.loaded))      -- table
-- 没有require模块文件
for i, v in pairs(package.loaded) do
    print(i,v)
end

--[[
>>>输出
string    table: 006EDE40
debug    table: 006EDF08
package    table: 006EDAF8
_G    table: 00501C88
io    table: 006EDC88
os    table: 006EDDC8
table    table: 006EDB98
math    table: 006EDEB8
]]

然后我们任意加载一个Demo.lua,代码如下:

-- requireDemo.lua
-- 内部实现代码: 
local requireDemo = {}
return true
require("requireDemo")
for i, v in pairs(package.loaded) do
    print(i,v)
end

--[[
输出:
string    table: 002DDE40
debug    table: 002DDF08
package    table: 002DDAF8
_G    table: 008C1C88
io    table: 002DDC88
os    table: 002DDDC8
table    table: 002DDB98
math    table: 002DDEB8
coroutine    table: 002DDA58
requireDemo    true                      -- 新加的,已经加入到表中了        
]]    

经过如上代码对比,我们可以这样理解,通过require加载某模块的时候,首先通过package.loaded来判定是否已加载。如果已加载,则返回该模块数据,如果没有加载,进行搜索加载,如果加载成功,返回该模块数据,否则报错。比如:

-- 加载不存在的模块
require("ErrorModel")

--[[
错误堆栈信息:
lua: require.lua:21: module 'ErrorModel' not found:
    no field package.preload['ErrorModel']
    no file '.\ErrorModel.lua'
    no file 'E:\Program Files (x86)\Lua\5.1\lua\ErrorModel.lua'
    no file 'E:\Program Files (x86)\Lua\5.1\lua\ErrorModel\init.lua'
    no file 'E:\Program Files (x86)\Lua\5.1\ErrorModel.lua'
    no file 'E:\Program Files (x86)\Lua\5.1\ErrorModel\init.lua'
    no file 'E:\Program Files (x86)\Lua\5.1\lua\ErrorModel.luac'
    no file '.\ErrorModel.dll'
    no file '.\ErrorModel51.dll'
    no file 'E:\Program Files (x86)\Lua\5.1\ErrorModel.dll'
    no file 'E:\Program Files (x86)\Lua\5.1\ErrorModel51.dll'
    no file 'E:\Program Files (x86)\Lua\5.1\clibs\ErrorModel.dll'
    no file 'E:\Program Files (x86)\Lua\5.1\clibs\ErrorModel51.dll'
    no file 'E:\Program Files (x86)\Lua\5.1\loadall.dll'
    no file 'E:\Program Files (x86)\Lua\5.1\clibs\loadall.dll'
stack traceback:
    [C]: in function 'require'
    require.lua:21: in main chunk
    [C]: ?
]]

对比着错误的堆栈信息,我们可以得到这样的信息:根据指定的搜索路径,查找了Lua和C中的相关文件。我们来详细的说明下:

在程序中,lua是通过LUA_PATH进行初始化,C是通过LUA_CPATH进行初始化的

// 在luaconf.h中
// Environment variable names for path overrides and initialization code
// 用于初始化和覆盖环境变量名
#define LUA_PATH    "LUA_PATH"
#define LUA_CPATH    "LUA_CPATH"

如果LUA_PATH,LUA_CPATH没有相关的变量,会通过LUA_PATH_DEFAULT,LUA_CPATH_DEFAULT来进行默认初始化,代码如下:

// luaconf.h中
/*
** In Windows, any exclamation mark ('!') in the path is replaced by the
** path of the directory of the executable file of the current process.
*/
#define LUA_LDIR    "!\\lua\\"
#define LUA_CDIR    "!\\"
#define LUA_PATH_DEFAULT \
  ".\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;"
#define LUA_CPATH_DEFAULT \
  ".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll"
#else
/*
** Note to distribution maintainers: do NOT patch the following lines!
** Please read ../doc/install.html#distro and pass PREFIX=/usr instead.
*/
#ifndef LUA_MULTILIB
#define LUA_MULTILIB    "lib"
#endif
#ifndef LUA_LMULTILIB
#define LUA_LMULTILIB    "lib"
#endif
#define LUA_LROOT    "/usr/local"
#define LUA_LUADIR    "/lua/5.1/"
#define LUA_LJDIR    "/luajit-2.1.0-beta2/"

#ifdef LUA_ROOT
#define LUA_JROOT    LUA_ROOT
#define LUA_RLDIR    LUA_ROOT "/share" LUA_LUADIR
#define LUA_RCDIR    LUA_ROOT "/" LUA_MULTILIB LUA_LUADIR
#define LUA_RLPATH    ";" LUA_RLDIR "?.lua;" LUA_RLDIR "?/init.lua"
#define LUA_RCPATH    ";" LUA_RCDIR "?.so"
#else
#define LUA_JROOT    LUA_LROOT
#define LUA_RLPATH
#define LUA_RCPATH
#endif

#define LUA_JPATH    ";" LUA_JROOT "/share" LUA_LJDIR "?.lua"
#define LUA_LLDIR    LUA_LROOT "/share" LUA_LUADIR
#define LUA_LCDIR    LUA_LROOT "/" LUA_LMULTILIB LUA_LUADIR
#define LUA_LLPATH    ";" LUA_LLDIR "?.lua;" LUA_LLDIR "?/init.lua"
#define LUA_LCPATH1    ";" LUA_LCDIR "?.so"
#define LUA_LCPATH2    ";" LUA_LCDIR "loadall.so"

#define LUA_PATH_DEFAULT    "./?.lua" LUA_JPATH LUA_LLPATH LUA_RLPATH
#define LUA_CPATH_DEFAULT    "./?.so" LUA_LCPATH1 LUA_RCPATH LUA_LCPATH2
#endif

初始化后,会将相关的路径分别放置到package.path,package.cpath中:

print("package.path路径相关:")
print(package.path)
--[[
-- 为了便于查看,进行了分行
;
.\?.lua;
E:\Program Files (x86)\Lua\5.1\lua\?.lua;
E:\Program Files (x86)\Lua\5.1\lua\?\init.lua;
E:\Program Files (x86)\Lua\5.1\?.lua;
E:\Program Files (x86)\Lua\5.1\?\init.lua;
E:\Program Files (x86)\Lua\5.1\lua\?.luac
]]

print("package.cpath路径相关:")
print(package.cpath)
--[[
-- 为了便于查看,进行了分行
.\?.dll;
.\?51.dll;
E:\Program Files (x86)\Lua\5.1\?.dll;
E:\Program Files (x86)\Lua\5.1\?51.dll;
E:\Program Files (x86)\Lua\5.1\clibs\?.dll;
E:\Program Files (x86)\Lua\5.1\clibs\?51.dll;
E:\Program Files (x86)\Lua\5.1\loadall.dll;
E:\Program Files (x86)\Lua\5.1\clibs\loadall.dll
]]

看到如上的输出,其模块名的显示"?",在lua中,其搜索的路径实质上属于模板路径,在搜索模块时,首先会把模块名替换模块路径下的"?",再进行开始搜索。

从实质上来说,搜索的步骤依次分为如下部分:

1. 预加载搜索,通过package.preload来进行

2. Lua中搜索,通过package.path获取搜索路径,成功后会调用loadFile加载

3. C库中搜索,通过package.cpath获取搜索路径,成功后,会调用loadlib来加载

加载成功后,会存储到表package.loaded中。

 

其它:能否重新加载模块吗?

答案可以,我们需要将已加载模块的表置空,如下:

package.loaded["*"] = nil      -- 置空已加载的模块数据
required("*")             -- 再次加载

 关于require的实现,代码如下:

-- 参考: Lua程序设计(第2版)
function
require(name) -- 判定模块是否已加载 if not package.loaded[name] then local loader = findloader(name) if loader == nil then error("unable to load module " .. name) end -- 将模块标记为已加载 package.loaded[name] = true -- 初始化模块 local res = loader(name) if res ~= nil then package.loaded[name] = res end end -- 返回模块数据 return package.loaded[name] end

 

转载于:https://www.cnblogs.com/SkyflyBird/p/7851752.html

(OSTrack)Joint Feature Learning and Relation Modeling for Tracking A One-Stream Framework Joint Feature Learning and Relation Modeling for Tracking A One-Stream Framework (OSTrack) 阅读详情

相关推荐

YOLOv11模型改进全攻略:利用轻量化模块实现精度与速度双跃升

如果你在实操中遇到模块替换导致的精度骤降或部署报错,不妨尝试调整轻量化模块的替换比例,或针对性地保留关键层的原始结构。记住,轻量化的核心是“在精度损失可接受的范围内最大化提升效率”,只要结合业务场景灵活取舍,你也能让YOLOv11在资源受限的环境中大放异彩。接下来,我们从模块选型到代码集成,一步步带你打造“轻量且能打”的YOLOv11,真正帮你解决工业落地中的效率与精度痛点。训练过程中关注模型的mAP和推理速度,若精度下降过多,可调整模块替换的比例(如仅替换Backbone的部分卷积层)。

m0_64661770的博客 472

Luarequire小结

Luarequire小结 在游戏开发中会经常使用到lua作为游戏逻辑层的脚本语言,各种优势就不说了,虽然平时用的比较多,但对lua语言本身和内部的一些实现并不是很了解,让我们先从luarequire入手来一探require的各种用法吧。 require其实类似与C/C++中的#include,就是加载一个指定名称的模块进来,该模块可以来自于lua,也可能来自于C/C++,在lua虚拟机启动时,默认会给我们预先加载好一些模块,保存在package.loaded中,我们可以实际打印一波看看: for k,

异次元的归来 1618

java基于springboot+vue二手交易平台论文和答辩ppt

java基于springboot+vue二手交易平台论文,计算机毕业设计论文,1万多字目 录第1章 绪 论11.1课题背景11.2 课题意义21.3 开发工具及技术21.4 国内外现状3第2章 系统分析52.1 可行性分析52.2总体设计原则62.3系统需求分析62.4 业务流程分析62.5 数据流图7第3章 系统设计93.1 系统功能设计93.2 数据库设计10第4章 系统实现154.1管理员功能模块164.2前台首页功能模块194.3用户功能模块194.4卖家功能模块19第5章 软件测试225.1软件测试的重要性225.2测试实例的研究与选择225.3测试环境与测试条件245.4系统运行情况245.5系统评价24第6章 总结25参考文献:26致谢27

Lua require 函数使用

Lua 的用户文档中我们知道 require("modName") 函数是用来加载模块的,而如果这个modName已经用require 加载过的,再调用require时,将直接返回模块的值。因为函数首先查找表, 检测 modName 是否被加载过, 如果被加载过了,直接返回 package.loaded[modName] 的值。

tianyexing2008的博客 2652

Luarequire

luarequire的用法和一种可行的热更方案

qq_35806062的博客 3778

lua require加载机制详解:路径与loader解析

加载器函数负责执行模块的初始化和加载逻辑,通常会返回一个值,loader返回的值会被存储在`package.loaded[modname]`中,作为已加载模块的引用。而require所使用的路径与传统的路径不同,require采用的路径是一连串的模式,其中每项都是一种将模块名转换为文件名的方式。这表示程序会首先尝试加载当前目录下的`.lua`和`.lc`文件,然后是`/usr/local`目录下的子目录及其`init.lua`文件。首先,要加载一个模块,就必须的知道这个模块在哪里。

tecoes的博客 722

Luarequire使用

一.require的作用 1. 加载指定的模块,相当与#include作用类似,加载了该模块,那么就可已使用模块中的全局函数和全局数据(如表等等) 注:实际上require “xxx”后,会将xxx中的全局函数和数据放到表_G中,所以也就能访问了。2.例子(1)main.lua require "test" require "showSome"(2)test.lua function C

和尚的专栏 5万+

Luarequire

在工作中碰到类似这样一种情况:local x = ...x变量不在函数中,这样的用法还是第一次见,所以自己敲了一个类似的例子,做个小标记。例子如下:--LuaTest.luaLuaTest = {} function LuaTest.DeclareFunc (moduleName) print("DeclareFunc output is ", moduleName) enddo l

maoliran的博客 1022

luarequire

Lua加载模块

for_tech的博客 3889

Lua中的require

主要翻译自lua文档,加上了programming lua中自己的一些理解 require(modname) 加载给定的模块.函数首先检查表package.loaded来判定modname是否已经存在.如果存在,则require返回package.loaded[modname]所存储的值否则它尝试为模块找到一个加载器(loader). 要找到一个加载器,require首先查询packag

4万+

Lua require的路径

lua require 加载方式与我们现在熟知的路径系统不太一样,想要知道lua require 方法的工作原理也很简单 随便写一个错误的require 代码即可: require("lala"); 这样运行会得到一个报错: 1>F:\Git\luatest\metaTest.lua:(56): module 'lala' not found: no field pa...

u012231702的博客 4424

LUA Require函数

Lua提供高级的require函数来加载运行库。粗略的说require和dofile完成同样的功能但有两点不同: require会搜索目录加载文件 require会判断是否文件已经加载避免重复加载同一文件。由于上述特征,requireLua中是加载库的更好的函数require使用的路径和普通我们看到的路径还有些区别,我们一般见到的路径都是一个目录列表。require的路径是一个模...

日月星辰的博客 6727

luarequire的使用

luarequire有几种用法。 1、加载文件     如果有一个test.lua的文件,可以这样加载 require("test")     如果test.lua不在可执行程序A当前目录下,则加上相应路径即可     如:A在目录X下,test.lua在X/lua/test.lua下,则这样写require("./lua/test")             windows下也可以这

woshiyuanlei的专栏 7984

Lua源码分析 - 扩展库篇 - 扩展库Require的实现(12)

我们前面几章节讲过,Lua函数调用有三种类型:C语言闭包函数,C 扩展库API和Lua语言函数。这一章我们主要讲解一下Lua的扩展库Require的实现。

自娱自乐的代码人 3617

Lua5.1中加载dll动态链接库的方法例子解析

请注意,这个过程可能涉及到一些平台特定的步骤,例如在 Windows 上设置正确的路径和依赖项。确保你的 Lua 环境已经配置好了对应的 C 库路径,这样 Lua 才能正确地找到和加载 DLL。在 Visual C++ 中,你需要创建一个 DLL 项目,并将上述代码添加到项目中。:首先,你需要编写一个 C 语言函数,这个函数将被编译到 DLL 中,并被 Lua 调用。:使用适当的编译器(如 Visual C++)将你的 C 代码编译成 DLL 文件。函数来加载 DLL 并调用其中的函数

IT老农民的博客 1342

Lua语言】被坑无数次后,试出require引用函数的简易用法

1、确保被引用文件和本体文件处于同一级目录 2、被引用文件什么都可以不用做,正常该怎么写就怎么写。 3、在本体文件写上:require “文件名” 4、指令和文件名之间要隔一个空格,且文件名要加引号(单引号、双引号都无所谓)。 5、后面就可以放心大胆地在本体文件里使用被引用文件的所有函数了。 6、以上就是最人性化,最不折腾用法的全部实用说明了~如有疑问,欢迎探讨!

qq_29202933的博客 550

34. Lua require 函数

【代码】34. Lua require 函数

Eden 的博客 671

(一)Node.js 模块化详解

(一)模块的分类 我们知道,在 node.js 中,通过 require 来引入外部模块,引入外部模块需要使用模块标识,通过模块标识来找到指定的模块。外部模块一般分为两大类:核心模块和文件模块 (1)核心模块 由Node本身提供的模块,模块标识是模块的名字 var path = require('path') (2)文件模块 由用户自己创建的模块,模块的标识是模块的路径 const ENV = require('../src/utils/env') (二)模块的本质 如何验证模块是函数

Luckyzhoufangbing的博客 406

Luarequire 函数

是模块加载系统的核心功能,用于动态加载和执行 Lua 模块。的这种设计使得 Lua 的模块系统既灵活又高效,是 Lua 生态的重要组成部分。

IMPYLH的博客 426
上一篇: cocos lua 创建替换图片
下一篇: lua math.random伪随机问题浅析
all36426
博客等级 码龄12年 2粉丝 0原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值