如何设置搜索路径以允许将Lua插件添加为包。
2013-10-30 0:6:40
收藏:0
阅读:98
评论:1
tl;dr:我想使用自定义目录名称模式创建Lua包,但在搜索路径方面遇到了问题。
问题
我有一个应用程序,想要允许用户编写插件,遵循类似于Lightroom的模型:
- 默认一组插件存储在
<app data>/plugins/<name>.myplugin中 <name>.myplugin是一个目录束,它可以包含一组脚本、二进制文件或其他资源- 插件可以通过不同的脚本向应用导出许多不同的函数
- 导出函数的名称在由应用读取的
info.lua文件中列出
我正在解决的问题是如何将插件封装为包(模块+子模块)或常规脚本。我设想插件可能会包括第三方模块:
Foo.myplugin/
info.lua - 返回包含插件名称、版本信息、已导出函数列表等的表
Foo.lua - 定义此插件导出的主要函数,调用其他脚本:
UsefulFunctions.lua - 被Foo.lua使用
3rdparty/3rdparty.lua - 第三方模块
如果我将包搜索路径package.path设置为
<appdata>/?.myplugin/?.lua
那么我可以使用Foo=require 'Foo'加载包。但是,我无法弄清楚如何加载子模块。如果Foo.lua调用UsefulFunctions=require 'UsefulFunctions',则此加载失败,因为Lua的搜索路径尝试查找UsefulFunctions.myplugin/UsefulFunctions.lua。出于类似原因,我也无法使用require 'Foo.UsefulFunctions'加载它。
一些选项:
- 一个解决方法是将每个插件的路径显式添加到包路径中,但是如果两个插件都包含具有相同名称的子模块,这将导致问题。
- 另一种选择是编写插件以使用常规lua脚本而不是提供模块,但这仍然意味着要在每个插件内设置搜索路径。
- 一种后备选项是丢失
.myplugin后缀,这将简化包搜索路径。 - 修补Lua以显式支持此类搜索路径
有没有办法提供我需要的功能?
我目前正在使用Lua 5.1。我知道5.2具有更多控制包搜索路径的功能,但我目前没有升级到它的选项。我还在使用luabind,尽管我认为它与此无关。
点赞
评论区的留言会收到邮件通知哦~
推荐文章
- 如何将两个不同的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 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
你可以使用自定义的搜索函数来自定义 Lua 模块的搜索方式,在 require 的文档 和
package.loaders中有介绍相应的机制。技巧在于检测模块是否在带有
.myplugins后缀的目录中,并跟踪捆绑包的路径。以下是相应的脚本示例。-- <appdata>/plugins/foo.myplugin/foo.lua local auxlib = require 'foo.auxlib' local M = {} function M.Foobnicator() print "Called: Foobnicator!!" auxlib.AuxFunction() end return M-- <appdata>/plugins/foo.myplugin/auxlib.lua local M = {} function M.AuxFunction() print "Called: AuxFunction!!" end return M-- main.lua package.path = package.path .. ";" .. [[<appdata>/plugins/?.myplugin/?.lua]] local bundles = {} -- holds bundle names and pathnames local function custom_searcher( module_name ) if string.match( module_name, '%.' ) then -- module name has a dot in it - it is a submodule, -- let's check if it is inside a bundle local main_module_name, subname = string.match( module_name, '^([^.]-)%.(.+)' ) local main_path = bundles[ main_module_name ] if main_path then -- OK, it's a submodule of a known bundle local sub_fname = string.gsub( subname, '%.', '/' ) -- replace main module filename with that of submodule local path = string.match( main_path, '^.*[/\\]' ) .. sub_fname .. '.lua' return loadfile( path ) else -- not a bundle - give up the search return end end -- search for the module scanning package.path for template in string.gmatch( package.path, '[^;]+' ) do if string.match( template, '%.myplugin' ) then -- bundle? local module_path = string.gsub( template, '%?', module_name ) local fh = io.open( module_path ) -- file exists? if fh then -- module found fh:close() bundles[ module_name ] = module_path return loadfile( module_path ) end end end end -- sets the custom searcher as the first one so to take -- precedence over default ones table.insert( package.loaders, 1, custom_searcher ) local foo = require 'foo' foo.Foobnicator()运行
main.lua将产生以下输出:Called: Foobnicator!! Called: AuxFunction!!希望这能让你找到正确的方向。可能它不能涵盖所有可能性,并且错误处理完全不完整,但它应该为你提供了一个很好的基础。