最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Lua中模塊以及實現(xiàn)方法指南

 更新時間:2015年04月10日 09:58:07   投稿:hebedich  
從Lua 5.1開始,我們可以使用require和module函數(shù)來獲取和創(chuàng)建Lua中的模塊。從使用者的角度來看,一個模塊就是一個程序庫,可以通過require來加載,之后便得到一個類型為table的全局變量。

從使用的角度來看,一個模塊就是一個程序庫,可以通過Lua自身提供的require來加載。然后便得到一個全局變量,表示一個table。這個table就是像一個名字空間,其內容就是模塊導出的所有東西,例如函數(shù)和常量。簡單的說,Lua中的模塊就是一個table,table中可以包括任何東西。本文首先詳細介紹模塊相關的require函數(shù),包括該函數(shù)的執(zhí)行流程以及查找模塊的路徑,然后介紹了實現(xiàn)模塊的三種方法,并給出相應的優(yōu)缺點。

 require函數(shù)

     該函數(shù)用來加載一個模塊,即按指定的路徑和傳入的參數(shù),查找要加載的模塊。函數(shù)原型如下:

      require (modname)

      該函數(shù)的執(zhí)行流程如下:

      I、查找表package.loaded,看modname是否已經加載過了。若是,則require函數(shù)直接返回package.loaded[modname],否則繼續(xù)執(zhí)行,尋找模塊的加載器(loader)。

      II、為了尋找加載器,require使用了數(shù)組package.searchers(Lua 5.2引入的,在之前的版本叫做package.loaders,實質兩者只是名字不同而已),數(shù)組中每個元素是一個函數(shù)。

     第一個函數(shù)用來是搜索表package.preload,若存在,則返回相應的加載器。

     第二個函數(shù)是用來獲取Lua模塊的加載器,其搜索路徑存儲在package.path中,它是一個字符串,比如:

復制代碼 代碼如下:

/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 

會用模塊名來替換每個”?”,然后根據(jù)替換的結果來檢測是否存在這樣的一個文件。這個工作是通過函數(shù)package.searchpath來做的。package.searchpath函數(shù)原型如下:
      package.searchpath (name, path [, sep [, rep]])

參數(shù)path是要查找的字符串,用分號隔開;name是要查找的文件;參數(shù)sep(默認值是”.”)可用于name中,在查找過程中用rep(默認值是系統(tǒng)目錄的分隔符)替換。比如path是

復制代碼 代碼如下:

"./?.lua;./?.lc;/usr/local/?/init.lua"

要查找foo.a,則會嘗試查找文件

復制代碼 代碼如下:

./foo/a.lua, ./foo/a.lc, 和/usr/local/foo/a/init.lua 

也就是說Lua支持具有層級性的模塊名。
      第三個函數(shù)是用來獲取C模塊的加載器,其搜索路徑存儲在package.cpath中,它也是一個字符串,比如:

復制代碼 代碼如下:

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

同樣會用模塊名來替換每個”?”,然后根據(jù)替換的結果來檢測是否存在這樣的一個文件。這個工作也是通過函數(shù)package.searchpath來做的。
     第四個函數(shù)是用all-in-one 加載器,使用這個功能,可以使得一個包里面包含多個C子模塊。除了第一個外,其他三個除了返回加載器外,還會返回找到的文件名作為額外的值。

      III、找到加載器后,require將用兩個參數(shù)調用這個加載器,一個是傳入的參數(shù)modname,另外一個是返回的額外值。如加載器返回一個不是nil的值,則把這個值賦值給package.loaded[modname]。如果加載返回返回一個nil并且加載器執(zhí)行完后package.loaded[modname]還為空,則把package.loaded[modname]賦值為true。不管那種情況,require都會返回package.loaded[modname]。如果在這個過程有任務錯誤,require函數(shù)就產生一個錯誤給調用者。

     最后關于require函數(shù),值得注意的幾點是:

     I、如果require找到的是一個lua文件,則通過loadfile來加載代碼,如果找到的是一個C程序庫,就通過loadlib來加載。注意,loadfile和loadlib都實質上加載代碼,并沒有運行他們。為了運行他們,require會用模塊名作為參數(shù)來調用這些代碼。

     II、若要強制使require對同一庫加載兩次,可以簡單刪除package.loaded中的模塊條目,即賦值相應的條目為nil。

     III、通過上面的加載過程分析知道,要加載自己的lua文件或C庫,可以通過修改package.path或package.cpath的值,把要搜索的路徑加載進去。

      IV、也可以定義自己的加載函數(shù)(除了已有的loadlib和loadfile等),比如加載ZIP文件,甚至從web上下載一個文件。

編寫模塊的方法

     方法一:對于Lua5.0和5.1來說,編寫模塊最簡單的方法是使用Lua自身提供的module函數(shù)(注意在Lua 5.2中被刪除了),比如要編寫一個模塊foo,模塊文件foo_file.lua如下:

復制代碼 代碼如下:

module("foo", package.seeall) 
function test() 
end 

則在其他文件要使用這個模塊,方式如下:

復制代碼 代碼如下:

require(“foo_file.lua”) 
foo.test() 

并且執(zhí)行require后,則會把模塊foo就是全局環(huán)境的一個變量了,在其他地方也可以使用。module函數(shù)原型如下:

復制代碼 代碼如下:

module (name [, ···]) 

module在創(chuàng)建模塊table之前,會先檢查package.loaded是否已包括了這個模塊,或者是否已存在與模塊同名的變量。如果由此找到了這個table,它就會復用這個table做為模塊。也就是說,可以用module來打開一個已創(chuàng)建的模塊。

對于module函數(shù)來說,有以下問題,比如在模塊文件module0_test中有:

復制代碼 代碼如下:

module("mymodule", package.seeall)                                                                      
function foo() 
    print("Hello World!") 
end 

在另外一個文件可以這樣使用這個模塊:

復制代碼 代碼如下:

require "module0_test" 
mymodule.foo()             --Hello World! 
mymodule.print("example")  --example 

對于第二個調用不是報錯的,并且是非常奇怪的,這時因為module機制是在模塊中找不的成員,則去_G全局變量找,實現(xiàn)方式類似如下:

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 
    setfenv(1, newenv) -- for 5.1 
  else 
    _ENV = newenv -- for 5.2 
  end 
end 

在模塊找不到的成員,則到_G中去查找,并且這樣訪問也是非常低效的,因為要通過元表來訪問成員。

 方法二:該方法的基本思想是讓模塊的主程序有一個獨占的環(huán)境,這樣所有函數(shù)或變量都共享這個table,并且所有的全局變量都記錄在這個table中,當然局部變量是不會的。代碼片段如下:

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 

如果這樣實現(xiàn),在模塊訪問_G中的變量時,需要加上前綴,比如_G.print。為了解決這個問題,有幾種方法,各有優(yōu)缺點:

 I、設置M的元表,即setmetable(M, {__index = _G})這樣做后,訪問全局變量,都要通過元表,開銷比較大。

 II、設置local _G = _G,這樣做后,訪問全局變量仍然要加上前綴,但速度更快。

 III、把模塊需要的全局變量都設置為局部變量,比如local io = io。這樣做會比較繁瑣,但是速度最快。

方法三:同樣是使用環(huán)境的概念。比如模塊文件如下:

復制代碼 代碼如下:

function foo()                                                                                          
    print("Hello World!")                                                                               
end 

為了使用它,方法如下:

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!” 

用這種方法,只需調用Import方法,其返回值就是模塊,該方法把模塊相關訪問工作,放在使用的模塊的地方了。

以上所述就是本文的全部內容了,希望能夠對大家學習lua有所幫助。

相關文章

  • Lua基礎教程之表(Table)學習筆記

    Lua基礎教程之表(Table)學習筆記

    這篇文章主要介紹了Lua基礎教程之表(Table)學習筆記,本文來自個人總結,需要的朋友可以參考下
    2014-09-09
  • lua日志文件處理代碼

    lua日志文件處理代碼

    本文給大家分享的是使用lua編寫的日志文件的處理代碼,非常的簡單實用,有需要的小伙伴可以參考下。
    2015-09-09
  • lua腳本語言快速入門教程

    lua腳本語言快速入門教程

    這篇文章主要介紹了lua腳本語言快速入門教程,本文講解了變量及常量、字符串、邏輯控制語句、循環(huán)結構、函數(shù)及其使用等內容,需要的朋友可以參考下
    2015-03-03
  • Lua中的模塊(module)和包(package)詳解

    Lua中的模塊(module)和包(package)詳解

    這篇文章主要介紹了Lua中的模塊(module)和包(package)詳解,本文講解了require函數(shù)、寫一個模塊、package.loaded、module函數(shù)等內容,需要的朋友可以參考下
    2014-09-09
  • Lua文件讀寫詳解

    Lua文件讀寫詳解

    這篇文章主要介紹了Lua文件讀寫詳解,本文講解了文件讀寫的簡單模型和完整模型,并給出了一個操作示例,需要的朋友可以參考下
    2015-04-04
  • Lua中全局變量與非全局環(huán)境介紹

    Lua中全局變量與非全局環(huán)境介紹

    這篇文章主要介紹了Lua中全局變量與非全局環(huán)境介紹,本文講解了全局變量的原形、非全局的環(huán)境、改變函數(shù)的全局變量環(huán)境、使用__index元方法保留原來的_G,需要的朋友可以參考下
    2014-09-09
  • Lua教程(六):綁定一個簡單的C++類

    Lua教程(六):綁定一個簡單的C++類

    這篇文章主要介紹了Lua教程(六):綁定一個簡單的C++類,本文是最后一篇C/C++與Lua交互的教程,其他教程請參閱本文下方的相關文章,需要的朋友可以參考下
    2014-09-09
  • Lua中編譯執(zhí)行代碼相關的函數(shù)詳解

    Lua中編譯執(zhí)行代碼相關的函數(shù)詳解

    這篇文章主要介紹了Lua中編譯執(zhí)行代碼相關的函數(shù)詳解的相關資料,需要的朋友可以參考下
    2015-04-04
  • Lua腳本語言簡介

    Lua腳本語言簡介

    這篇文章主要介紹了Lua腳本語言簡介,Lua最著名的應用是在暴雪公司的網(wǎng)絡游戲WOW中, Lua腳本可以很容易的被C/C++代碼調用,也可以反過來調用C/C++的函數(shù),這使得Lua在應用程序中可以被廣泛應用,本文就是對Lua語言的詳細介紹,需要的朋友可以參考下
    2014-09-09
  • Lua中函數(shù)的幾個特別之處探究

    Lua中函數(shù)的幾個特別之處探究

    這篇文章主要介紹了Lua中函數(shù)的幾個特別之處探究,本文講解了Lua的函數(shù)創(chuàng)建、函數(shù)的參數(shù)、函數(shù)參數(shù)個數(shù)自適應、函數(shù)多重返回值等內容,需要的朋友可以參考下
    2014-09-09

最新評論

宝兴县| 吴堡县| 牟定县| 盐池县| 平潭县| 涟水县| 清丰县| 衡水市| 娄烦县| 乃东县| 虞城县| 曲麻莱县| 蚌埠市| 克东县| 昭通市| 沁源县| 黔东| 揭西县| 侯马市| 正安县| 香港| 旺苍县| 蚌埠市| 奇台县| 双峰县| 平罗县| 铁岭县| 城市| 临桂县| 沙雅县| 玉田县| 乌苏市| 陕西省| 双牌县| 滨州市| 象山县| 福清市| 顺平县| 西安市| 宁陵县| 永清县|