1. 程式人生 > >【lua】C 函式中呼叫Lua函式時,對於lua_pcall使用的困惑

【lua】C 函式中呼叫Lua函式時,對於lua_pcall使用的困惑

最近在學習使用Lua,也通過基本的語法知識完成了公司的一個關於配置檔案引數合法性檢查的小任務。雖然任務完成了,但對於一些函式的呼叫目的還是搞不明白,這兩天再次重看了Manual Reference,稍微梳理出了一點眉目,記錄在此。

首先看一段小小小程式

function printmsg() print("hello world") end   x = 10

//test.c

    #include <stdio.h>     #include <unistd.h>           #include <lua.h>     #include <lauxlib.h>     #include <lualib.h>           int main(int argc, const char *argv[])     {         lua_State *L;         if(NULL == (L = luaL_newstate()))         {             perror("luaL_newstate failed");             return -1;         }         luaL_openlibs(L);         if(luaL_loadfile(L, "./test.lua"))         {             perror("loadfile failed");             return -1;         }         lua_pcall(L, 0, 0, 0); //一直這樣用,但是一直不明白為什麼一定要加這一句話               lua_getglobal(L, "printmsg");         lua_pcall(L, 0, 0, 0);               lua_close(L);               return 0;     }

上面的程式碼就是在test.c中呼叫test.lua的函式printmsg函式

對於上面的C程式碼,我想大家都知道幾個函式的大概作用:

luaL_newstate():建立一個新的Lua虛擬機器

luaL_openlibs() :開啟一些必要的庫,比如print等

lua_loadfile():手冊上寫的是"This function uses lua_load to load the chunk in the filenamed filename." 而lua_load就是把編譯過的chunk放在stack的頂部。理解chunk很重要,後面會具體講到

lua_pcall : 執行棧上的函式呼叫

一開始我一直認為既然luaL_loadfile執行以後,就可以直接嗲用lua_getglobal獲得test.lua中的函式,其實不然。手冊中明確提到,lua_load把一個lua檔案當作一個chunk編譯後放到stack的棧頂,而什麼是chunk呢?chunk就是一個可執行語句的組合,可以是一個檔案也可以是一個string

“Lua handles a chunk as the body of an anonymous function with a variable number of arguments” 這是Lua對chunk也就是lua檔案的處理方式,就是認為是一個可變引數的匿名函式。也就是說,呼叫後棧上有一個匿名函式,這個函式的body就是檔案中所有的內容。

在luaL_loadfile後,呼叫lua_getop以及lua_type可以知道棧的大小為1,放在棧上的是一個fucntion型別的value。為什麼loadfile後我們不能直接獲取到printmsg這個函式呢,那是因為剛才提到的,loadfile僅僅視編譯lua檔案,並不執行這個檔案,也就是說只是在棧上形成了一個匿名函式。只有執行這個函式一次,才會使得printmsg可以通過lua_getglobal獲取,否則,全域性變數是空的。我在手冊上看到這樣一句話:Lua在執行函式的時候,函式會例項化,獲得的closure也是這個函式的最終值。其實不管視函式,還是其他型別,如果不執行的話,它們只是被編譯,並不能在程序的空間種獲取到他們,感覺就像c的庫一樣,他們的編譯檔案.so已經存在,但是如果你不呼叫它,那麼庫中所有的變數不能被例項化,呼叫者也就無法訪問。其實pringmsg和x本質是一樣的,只是他們型別不同而已。 --------------------- 作者:rio_dog 來源:CSDN 原文:https://blog.csdn.net/rio_dog/article/details/6754778 版權宣告:本文為博主原創文章,轉載請附上博文連結!