Lua 使用过程的一个理解(lua_pcall(L, 0, 0, 0);)


首先看一段小小小程序

//test.lua

  1. function printmsg()  
  2. print("hello world")  
  3. end  
  4.   
  5. x = 10  

//test.c

  1. #include <stdio.h>  
  2. #include <unistd.h>  
  3.   
  4. #include <lua.h>  
  5. #include <lauxlib.h>  
  6. #include <lualib.h>  
  7.   
  8. int main(int argc, const char *argv[])  
  9. {  
  10.     lua_State *L;  
  11.     if(NULL == (L = luaL_newstate()))  
  12.     {  
  13.         perror("luaL_newstate failed");  
  14.         return -1;  
  15.     }  
  16.     luaL_openlibs(L);  
  17.     if(luaL_loadfile(L, "./test.lua"))  
  18.     {  
  19.         perror("loadfile failed");  
  20.         return -1;  
  21.     }  
  22.     lua_pcall(L, 0, 0, 0); //一直这样用,但是一直不明白为什么一定要加这一句话  
  23.   
  24.     lua_getglobal(L, "printmsg");  
  25.     lua_pcall(L, 0, 0, 0);  
  26.   
  27.     lua_close(L);  
  28.   
  29.     return 0;  
  30. }  


上面的代码就是在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 filenamedfilename." 而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本质是一样的,只是他们类型不同而已。

你可能感兴趣的:(Lua 使用过程的一个理解(lua_pcall(L, 0, 0, 0);))