简体   繁体   English

Lua-如何动态调用模块?

[英]Lua - How do I dynamically call a module?

Here's some much-simiplified Lua code I'm working with. 这是我正在使用的一些非常简化的Lua代码。 I need to know how to dynamically call another module ('zebra'): 我需要知道如何动态调用另一个模块(“斑马”):

avar = require "avar"
bvar = require "bvar"

function create(zebra)
  print(zebra.new())
end

print(create(avar))

And here are two modules: 这是两个模块:

local Avar = {}

function Avar.new()
  return "avar"
end

return Avar

local Bvar = {}

function Bvar.new()
  return "new"
end

function Bvar.old()
  return "old"
end

return Bvar

If I try to pass in the string "avar" to my 'create' function, it doesn't work. 如果我尝试将字符串“ avar”传递给我的'create'函数,它将无法正常工作。 If I pass in the word 'avar' with no quotes, it does work, however, I don't understand what avar with no quotes is? 如果我输入不带引号的'avar'一词,它确实有效,但是,我不明白什么是不带引号的avar? It seems to be a blank table? 好像是一张空白的桌子? Not sure how to pass a blank table as an argument in my main program. 不确定如何在我的主程序中将空白表作为参数传递。

But maybe I'm totally on the wrong path. 但是也许我完全走错了道路。 How do I dynamically call modules? 如何动态调用模块?

avar without the quotes is a global variable you created. 不带引号的avar是您创建的全局变量。 It is initialized to the value returned by the require function 1 , which is the value returned by the module you are invoking. 它被初始化为require函数1返回的值,这是您正在调用的模块返回的值。 In this case, its a table with the new field that happens to be a function. 在这种情况下,其带有new字段的表恰好是一个函数。

1 Importing a modules in Lua is done via regular functions instead of a special syntax. 1在Lua中导入模块是通过常规函数而不是特殊语法完成的。 The function call parenthesis can be ommited because parens are optional if you write a function call with a single argument and that argument is a string or a table. 可以省略函数调用括号,因为如果使用单个参数编写函数调用并且该参数是字符串或表,则括号是可选的。

Other than that, there are also some other things you are confusing here: 除此之外,这里还有其他一些令人困惑的事情:

  • The table you are storing on avar is not empty! 您存储在avar上的表不为空! You can print its contents by doing for k,v in pairs(avar) do print(k,v) end to see that. 您可以通过for k,v in pairs(avar) do print(k,v) end执行for k,v in pairs(avar) do print(k,v) end来打印其内容for k,v in pairs(avar) do print(k,v) end来看看。

  • The avar , bvar and create variables are global by default and will be seen by other modules. 默认情况下, avarbvarcreate变量是全局变量,其他模块将看到它们。 Most of the time you would rather make them local instead. 大多数时候,您宁愿将它们设置为本地。

     local avar = -- ... local bvar = -- ... local function create (zebra) -- ... end 
  • The create function clearly expects a table since it does table indexing on its argument (getting the new key and calling it). create函数显然希望有一个表,因为它会对参数进行表索引(获取new键并调用它)。 The string doesn't have a "new" key so it won't work. 该字符串没有“新”键,因此无法使用。

  • You aren't really dynamically calling a module. 您并不是真正地动态调用模块。 You are requiring that module in a regular way and it just happens that you pass the module return value into a function. 您需要以常规方式使用该模块,并且恰好将模块返回值传递给函数。

  • create always returns nil so there is no point in doing print(create(avar)) . create始终返回nil所以执行print(create(avar))没有意义。 You probablu want to modify create to return its object instead of printing it. 您可能要修改create以返回其对象,而不是打印它。

You can require any time: 您可以要求任何时间:

function create(zebraModuleName)
  zebraType = require(zebraModuleName)
  print(zebraType .new())
end

print(create("avar"))
print(create("bvar"))

You can use standard require from lua language or build your own loader using metatables/metamethods. 您可以使用lua语言中的标准require ,也可以使用元表/元方法构建自己的加载器。

1. create a global function: 1.创建全局函数:

function dynrequire (module)                                                                                           
  return setmetatable ({},{
    __index = function (table,key)
      return require(module..'.'..key)
    end
  })
end

2. Create your project tree visible to package.path 2.创建对package.path可见的项目树

./MySwiss/
  \___ init.lua
  \___ cut.lua
  \___ glue.lua
  \___ dosomething.lua

3. Make your module dynamic you only need to put this line on your MySwiss/init.lua (as if you were namespacing a PHP class): 3.使模块动态化,您只需要将此行放在MySwiss/init.lua (就像您命名一个PHP类一样):

return dynrequire('MySwiss')

4. Require your module and use subproperties dynamically On your script you only need to require MySwiss, and the folder file (or subfolders with dynrequire('MySwiss.SubFolderName') . 4.要求模块并动态使用子属性在脚本上,您仅需要MySwiss和文件夹文件(或带有dynrequire('MySwiss.SubFolderName')子文件夹。

var X = require('MySwiss')
X.glue()

Note that MySwiss doesn't have glue key. 请注意,MySwiss没有胶合键。 But when you try access de glue key the metamethod __index try to require submodule. 但是,当您尝试访问胶合键时,元方法__index会尝试需要子模块。 You can the full project tree using this technique. 您可以使用此技术构建完整的项目树。 The only downside is the external dependencies not packed this way. 唯一的缺点是没有以这种方式打包的外部依赖项。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM