Modules in Lua and guidelines for implementation _lua

Source: Internet
Author: User
Tags function prototype lua

From the point of view of use, a module is a library of libraries that can be loaded through the require provided by LUA itself. Then we get a global variable that represents a table. This table is like a namespace, and its contents are everything that the module exports, such as functions and constants. Simply put, the module in Lua is a table,table that can include anything. In this paper, the Require function of the module is introduced in detail, including the execution flow of the function and the path of the search module, then the three methods of implementing the module are introduced, and the corresponding advantages and disadvantages are given.

Require function

This function is used to load a module that locates the module to be loaded by the specified path and incoming parameters. The function prototype is as follows:

Require (ModName)

The execution flow of the function is as follows:

I, look up table package.loaded, see if ModName has been loaded. If so, the Require function returns directly to Package.loaded[modname], otherwise it continues, looking for the module's loader (loader).

II, in order to find the loader, require used the array package.searchers (Lua 5.2 introduced, in the previous version is called Package.loaders, in essence the two are only different names), the array of each element is a function.

The first function is used to search the table package.preload, and if so, the corresponding loader is returned.

The second function is used to get the loader for the Lua module, whose search path is stored in Package.path, which is a string, such as:

Copy Code code as follows:

/usr/local/share/lua/5.2/? Lua;/usr/local/share/lua/5.2/?/init.lua;/usr/local/lib/lua/5.2/? Lua;/usr/local/lib/lua/5.2/?/init.lua;. /?. Lua

Replaces each "?" with the module name, and then detects the existence of such a file based on the result of the substitution. This work is done through function Package.searchpath. The Package.searchpath function prototype is as follows:
Package.searchpath (name, path [, Sep [, Rep]])

Parameter path is the string to find, separated by semicolons; name is the file to find; parameter Sep (the default is.) Can be used in name and is replaced with rep (the default is the delimiter of the system directory) during the lookup. For example, path is

Copy Code code as follows:

"./?. Lua;. /?. Lc;/usr/local/?/init.lua "

To find FOO.A, you will try to find the file

Copy Code code as follows:

./foo/a.lua,./FOO/A.LC, and/usr/local/foo/a/init.lua

This means that LUA supports a hierarchical module name.
The third function is used to get the loader for the C module, whose search path is stored in Package.cpath, and it is also a string, such as:

Copy Code code as follows:

/usr/local/lib/lua/5.2/? so;/usr/local/lib/lua/5.2/loadall.so;. /?. So

It also replaces each "?" with the module name, and then detects if a file exists based on the result of the substitution. This work is also done through function Package.searchpath.
The fourth function is to use the All-in-one loader, which enables you to include multiple C sub modules in a package. In addition to the first, the other three will return the found file name as an extra value in addition to the loader.

III, after the loader is found, require will call the loader with two parameters, one for the incoming parameter modname and one for the extra value returned. If the loader returns a value that is not nil, assign the value to Package.loaded[modname]. If the load returns a nil and the loader finishes Package.loaded[modname] is empty, the Package.loaded[modname is assigned to true. In either case, require will return to Package.loaded[modname]. If there is a task error in this process, the Require function produces an error to the caller.

Finally, on the Require function, some noteworthy points are:

If require finds a LUA file, the code is loaded through LoadFile, and if a C program library is found, it is loaded by loadlib. Note that both LoadFile and loadlib actually load the code and do not run them. To run them, require calls the code with the module name as a parameter.

II, to force the require to load the same library two times, you can simply delete the module entry in package.loaded, that is, assign the corresponding entry as nil.

III, through the above load process analysis know, to load their own LUA files or C library, you can modify the value of Package.path or Package.cpath, the path to search to load.

IV, you can also define your own load functions (in addition to existing loadlib and loadfile, etc.), such as loading a zip file, or even downloading a file from the Web.

Ways to write a module

method One : For Lua5.0 and 5.1来, the easiest way to write a module is to use the module functions provided by LUA itself (note that it was removed in Lua 5.2), for example, to write a module foo, the module file Foo_file.lua as follows:

Copy Code code as follows:

Module ("foo", Package.seeall)
function test ()
End

You will use this module in other files in the following ways:

Copy Code code as follows:

Require ("Foo_file.lua")
Foo.test ()

And after executing the Require, the module foo is a variable of the global environment and can be used elsewhere. The module function prototype is as follows:

Copy Code code as follows:

Module (name [, ...])

Before the module table is created, the module checks to see if package.loaded has already included it, or if a variable with the same name as the module already exists. If this table is found, it will reuse this table as a module. In other words, you can use module to open a created block.

For the module function, there are the following issues, such as the module0_test in the modules file:

Copy Code code as follows:

Module ("MyModule", Package.seeall)
function foo ()
Print ("Hello world!")
End

In another file This module can be used in this way:

Copy Code code as follows:

Require "Module0_test"
Mymodule.foo ()--hello world!
Mymodule.print ("Example")--example

For the second call is not an error, and is very strange, at this time because the module mechanism is not found in the modules of the members, then go to _g global variables to find, the implementation is similar to the following:

Do local 
  globaltbl = _g local 
  newenv = setmetatable ({}, { 
    __index = function (t, k) Local 
      v = t[k] 
      if v = = Nil then return globaltbl[k] End return 
      v end 
    , 
    __newindex = M, 
  }) 
  if setfenv 
    then Setfen V (1, newenv)--for 5.1 
  else 
    _env = newenv--for 5.2 
  end 
 

A member that is not found in a module is searched in _g, and this access is also very inefficient because the members are accessed through the meta table.

method Two : The basic idea of this method is to have an exclusive environment for the main program of the module, so that all functions or variables share the table, and all global variables are recorded in this table, but local variables are not. The code snippet is as follows:

Local Modename = ... 
Local m = {} 
_g[modename] = M 
package.loaded[modname] = M 
if Setfenv then 
  setfenv (1, newenv) – for 5.1
   else 
  _env = newenv--for 5.2 
End 

If you do this, you need to prefix the module when accessing variables in _g, such as _g.print. To solve this problem, there are several methods, each with advantages and disadvantages:

I, set M of the meta table, that is, setmetable (m, {__index = _g}) After doing so, access to global variables, all through the meta table, the cost is relatively large.

II, set the local _g = _g, when you do so, access the global variable still has to prefix, but faster.

(III) Set the global variables required by the module to local variables, such as locally io = io. This can be tedious, but the fastest.

method Three : The same is the concept of using the environment. For example, the module file is as follows:

Copy Code code as follows:

function foo ()
Print ("Hello world!")
End

To use it, the method is as follows:

Local function Import (filename)                                     
  f = loadfile (filename) Local                                        
  m = {}                                             
  setmetatable (m, {__index = _g})                                   
  Setfenv (F,m) () return M-end local 
 
FOO = Import ("Module2_test.lua") 
 
Foo.foo ()--output "Hello world!" 

In this way, simply call the import method, the return value is the module, the method of the module-related access to work, the use of the module where the.

The above is the entire contents of this article, I hope to be able to learn from Lua help.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.