从字符串动态创建 Lua 模块
2020-8-28 13:15:44
收藏:0
阅读:203
评论:2
我处于以下情况中(请不要质疑我的动机):
我有一个 Lua 脚本 foo.lua,它需要一些模块 bar,即:
-- foo.lua
require 'bar'
-- 更多代码
然而却没有实现此模块的 bar.lua 文件。相反,我想要做的是从另一个脚本 main.lua 中执行 foo.lua,该脚本还应该 _从字符串动态创建模块 bar_(字符串来自何处并不重要),即:
-- main.lua
-- 以某种方式创建模块 `bar`,使得 `foo.lua` 中的 `require bar` 能够成功
dofile('foo.lua')
这是可能的吗?
点赞
用户11740758
我在游戏内使用 Lua 控制台执行类似于 load() 函数的东西。目的是让所需的 Lua 文件只包含字符串并返回它们。就像这样的文件:
return {
cmd=[[return function(cm) cm=io.popen(cm, 'r') cm=cm:read('a+') return cm end]]
}
然后你可以这样操作:
love.code=require('more_functions')
love.cmd=load(love.code.cmd)()
我的 require() 里还有一个安装代码将它们都放到正确的位置。我设置了一个带有已定义函数的元表,整个看起来就像这样:
-- Name: koys.lua
return {
cat=[[return function(cat) for line in io.lines(cat) do io.write(string.format('%s\n',line)) end end]],
free=[[return function() local a=(collectgarbage('count')*1024) print('Before:',a,'Byte') collectgarbage() print('After:',(collectgarbage('count')*1024),'Byte') a=a-collectgarbage('count')*1024 print('Freed:',a,'Byte') return a end]],
gauss=[[return function(gauss) return ((gauss*gauss+gauss)/2) end]],
shell=[[return function(shell) if (type(shell)=='string') then os.execute(shell) else os.execute('/bin/bash') end end]],
cmd=[[return function(cm) cm=io.popen(cm, 'r') cm=cm:read('a+') return cm end]],
len=[[return function(len) local incr=0 for _ in pairs(len) do incr=incr+1 end return incr end]],
dump=[[return function(dump) for key,value in pairs(dump) do io.write(string.format("%s=%s=%s\n",key,type(value),value)) end end]],
help=[[return function(help) love.dump(getmetatable(help).__index) end]],
printf=[[return function(prf,...) io.write(prf:format(...)) end]],
bl=[[return function(r,g,b,a) love.rrand=function() return r end love.grand=function() return g end love.brand=function() return b end love.arand=function() return a end end]],
install=[[getmetatable(love).__index.cmd=load(package.loaded.koys.cmd)()
getmetatable(love).__index.cat=load(package.loaded.koys.cat)()
getmetatable(love).__index.dump=load(package.loaded.koys.dump)()
getmetatable(love).__index.free=load(package.loaded.koys.free)()
getmetatable(love).__index.len=load(package.loaded.koys.len)()
getmetatable(love).__index.gauss=load(package.loaded.koys.gauss)()
getmetatable(love).__index.shell=load(package.loaded.koys.shell)()
getmetatable(love).__index.printf=load(package.loaded.koys.printf)()
getmetatable(love).__index.help=load(package.loaded.koys.help)()
getmetatable(love).__index.bl=load(package.loaded.koys.bl)()
getmetatable(love).__index.info=debug.getinfo
getmetatable(love).__index.cmd=load(package.loaded.koys.cmd)()
getmetatable(love).__index.concat=table.concat
getmetatable(love).__index.remove=table.remove
getmetatable(love).__index.unpack=table.unpack
getmetatable(love).__index.insert=table.insert
getmetatable(love).__index.sort=table.sort
getmetatable(love).__index.move=table.move
getmetatable(love).__index.pack=table.pack]]
}
之后只需要这样:
love.code=require('koys') -- 这个是包含 Lua 代码文本元素的表
setmetatable(love,{__index={}}) -- ...这将扩展 love...
load(love.code.install)() -- ...并结合元方法。
之后,在表 love 中你就可以通过运行以下命令来显示其内部内容:
love:dump()
或者使用以下命令来显示元表的内容:
love:help()
2020-08-28 16:36:42
评论区的留言会收到邮件通知哦~
推荐文章
- Lua 虚拟机加密load(string.dump(function)) 后执行失败问题如何解决
- 我想创建一个 Nginx 规则,禁止访问
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?


我认为最好的方法是使用
package.preload,它可以使你为给定的模块名称分配一个模块解析器函数:local myBar = { message = "Hello from BAR!" } package.preload['bar'] = function(...) return myBar end你也可以直接在
package.loaded中设置模块,这样可以覆盖已加载的模块,供下一次调用 require() 使用:local myBar = { message = "Hello from BAR!" } local myBar2 = { message = "I've changed!" } -- 使用 `package.loaded` 来表示我们已经加载过它了 package.loaded['bar'] = myBar print(require('bar').message) package.loaded['bar'] = myBar2 print(require('bar').message)如果你需要更加动态,也可以重写 require 函数:
local myBar = { message = "Hello from BAR!" } local oldRequire = require function require(name) if name == "bar" then return myBar end return oldRequire(name) end local bar = require("bar") print("Bar says: '"..bar.message.."'")你可以查看模块文档。
package.searchers看起来很有前途,可以进行通用的加载,但我好像无法修改它以包含自己的加载器。