【Lua基础系列】之C/C++与lua的交互方式(记我第一天上班)

 

a

                【Lua基础系列】之C/C++与lua的交互方式

 

    大家好,我是Lampard~~

    欢迎来到Lua基础系列的博客

    PS:本博客知识参考资料为:《Lua程序设计第四版》,该书由Lua的创始人2018年所编著,所以大家可以放心去吸收知识

   

   今天在正文之前先说一些心里话:

   今天是我正式工作的第一天,感觉到自己真真正正要从学生转化成社会里的大人了。虽有准备,但心里总是戚戚。

   公司是个好公司,第一天上班能感受到周围人的善意,对那里的伙食我已经很明显感觉到我将要长胖了。项目组里正在赶一个上

线项目,只有我一个人在碎碎的看着文档,这种落差无力感让人心里不舒服。不管怎么说,赶快成长起来吧。

 

    前文再续,书接上一回。

    今天讲的是如何在lua中如何实现与C/C++的交互:

    谜底直接告诉大家,它们是通过一个虚拟,强大的栈来进行交互。这个栈是由lua实现的。C方面只是通过取栈得到想要的数

据,然后再通过往这个栈中压入元素,从而实现向Lua那边更新数据。这个强大的栈长这样:

          

 

 TValue结构对应于lua中的所有数据类型, 是一个{值, 类型} 结构, 这就lua中动态类型的实现, 它把值和类型绑在一起, 用tt记录value的类型, value是一个联合结构, 由Value定义, 可以看到这个联合有四个域, 先说明简单的

        p -- 可以存一个指针, 实际上是lua中的light userdata结构

        n -- 所有的数值存在这里, 不过是int , 还是float

        b -- Boolean值存在这里, 注意, lua_pushinteger不是存在这里, 而是存在n中, b只存布尔

        gc -- 其他诸如table, thread, closure, string需要内存管理垃圾回收的类型都存在这里

        gc是一个指针, 它可以指向的类型由联合体GCObject定义, 从图中可以看出, 有string, userdata, closure, table, proto, upvalue, thread

    从下面的图可以的得出如下结论:

        1. lua中, number, boolean, nil, light userdata四种类型的值是直接存在栈上元素里的, 和垃圾回收无关.

        2. lua中, string, table, closure, userdata, thread存在栈上元素里的只是指针, 他们都会在生命周期结束后被垃圾回收.

    

    好,当我们有了这个强大的栈之后,究竟要如何使用他呢?

    假设我们有一个lua的文件如下:

str = "I am so cool"  
tbl = {name = "shun", id = 20114442}  
function add(a,b)  
    return a + b  
end

     现在向大家展示怎么去调用它:

#include <iostream>  
#include <string.h>  
using namespace std;  
   
extern "C"  
{  
    #include "lua.h"           
    #include "lauxlib.h"          // externC语言与lua交互的方式
    #include "lualib.h"  
}  
void main()  
{  
    //1.创建Lua状态  
    lua_State *L = luaL_newstate();      // L是一个强大的struct,里面封装了lua的八种数据类型 
    if (L == NULL)  
    {  
        return ;  
    }  
   
    //2.加载Lua文件  
    int bRet = luaL_loadfile(L,"hello.lua");  // L加载了“hello。lua”这个文件
    if(bRet)  
    {  
        cout<<"load file error"<<endl;  
        return ;  
    }  
   
    //3.运行Lua文件  
    bRet = lua_pcall(L,0,0,0);                 /*第一次调用是相当于 把一整个lua文件的内容 当成一个function来执行
												你可以试一下  lua 设置个全局变量a为100 先把整个文件load一次 
												读下看看 a为多少  再pcall一次 看看a为多少就知道了
												第一次调用a 得到的是nil 但是第2次调用就可以获得100了*/ 
    if(bRet)  
    {  
        cout<<"pcall error"<<endl;  
        return ;  
    }  
   
    //4.读取变量  
    lua_getglobal(L,"str");  				  // 把str置于栈顶
    string str = lua_tostring(L,-1);  	      // 把L转化tostring为C++类的str
    cout<<"str = "<<str.c_str()<<endl;        //str = I am so cool~  
   
    //5.读取table  
    lua_getglobal(L,"tbl");                 // 把tbl置在栈顶
    lua_getfield(L,-1,"name");              // 访问L中第一个元素(表)的name属性置于栈顶
    str = lua_tostring(L,-1);  
    cout<<"tbl:name = "<<str.c_str()<<endl; //tbl:name = shun  
   
    //6.读取函数  
    lua_getglobal(L, "add");        // 函数压入栈顶  
    lua_pushnumber(L, 10);          // 压入第一个参数 
    lua_pushnumber(L, 20);          // 压入第二个参数  
    int iRet= lua_pcall(L, 2, 1, 0);// 调用函数,调用完成以后,会将返回值压入栈中,2表示参数个数,1表示返回结果个数。  
    if (iRet)                       // 调用出错  
    {  
        const char *pErrorMsg = lua_tostring(L, -1);  
        cout << pErrorMsg << endl;  
        lua_close(L);  
        return ;  
    }  
    if (lua_isnumber(L, -1))        //取值输出  
    {  
        double fValue = lua_tonumber(L, -1);  
        cout << "Result is " << fValue << endl;  
    }  
   
    //至此,栈中的情况是:  
    //=================== 栈顶 ===================   
    //  索引  类型      值  
    //   4   int:      30   
    //   3   string:   shun   
    //   2   table:     tbl  
    //   1   string:    I am so cool~  
    //=================== 栈底 ===================   
   
    //7.关闭state  
    lua_close(L);  
    return ;  
}

 是不是很简单? OK,今天的博客就到这里,谢谢大家!!!

©️2020 CSDN 皮肤主题: 大白 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值