【lua】C 函数中调用Lua函数时,对于lua_pcall使用的困惑

https://blog.csdn.net/u010782644/article/details/79641284

https://blog.csdn.net/xingxinmanong/article/details/76047273

https://blog.csdn.net/VermillionTear/article/details/50943167

推荐结合这篇读:https://www.jb51.net/article/55847.htm

最近在学习使用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()))        //创建一个新的Lua虚拟机
        {
            perror("luaL_newstate failed");
            return -1;
        }
       
       luaL_openlibs(L);                        //打开一些必要的库,比如print等
        
       if(luaL_loadfile(L, "./test.lua"))
        {
            perror("loadfile failed");
            return -1;
        }
        lua_pcall(L, 0, 0, 0); //一直这样用,但是一直不明白为什么一定要加这一句话--执行栈上的函数调用.
//只有执行这个函数一次,才会使得printmsg可以通过lua_getglobal获取
     
        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
版权声明:本文为博主原创文章,转载请附上博文链接!

 

Lua和C++交互详细总结

一、Lua堆栈

要理解Lua和C++交互,首先要理解Lua堆栈。

简单来说,Lua和C/C++语言通信的主要方法是一个无处不在的虚拟栈。栈的特点是先进后出。

在Lua中,Lua堆栈就是一个struct,堆栈索引的方式可是是正数也可以是负数,区别是:正数索引1永远表示栈底,负数索引-1永远表示栈顶。如图:

 

更多:https://www.cnblogs.com/sevenyuan/p/4511808.html

用法

lua_pcall(lua_State *L,int nargs,int nresults,int errfunc)

    1

    nargs 参数个数
    nresults 返回值个数
    errFunc 错误处理函数,0表示无,表示错误处理函数在栈中的索引

示例

--test.lua
function test(x,y)
    return x + y
end
lua_loadfile(L,"test.lua");

--调用
lua_pushnumber(L,10);   --x 值入栈
lua_pushnumber(L,20);   --y 值入栈
lua_pcall(L,2,1,0); -- 2个参数-->从栈顶取出2个参数,生成一个结果,错误函数为0,10+20 结果放回栈顶=30

如果没有错误此时栈顶的值为30

如果运行出错,lua_pcall会返回一个非零的结果,如果指定了错误处理函数会先调用错误处理函数,然后再将错误信息入栈,在将返回结果和错误信息入栈之前会先将函数和参数从栈中移除。错误处理函数必须在被调用函数和其他参数之前入栈

原文:https://blog.csdn.net/u010782644/article/details/79641284
 

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值