Lua教程(二):C++和Lua相互传递数据示例_Lua

这是我的Lua系列教程的第二篇,本篇文章主要介绍C++和Lua相互传递数据。如果你还不知道怎么在c/c++里面调用Lua脚本的话,请参考这篇文章. 本文主要介绍基本数据类型的传递,比如整形(int),字符串(string)、数字(number)及bool值。

加载并运行Lua脚本

由于在上一个教程里面已经介绍过如何在C/C++里面嵌入Lua,所以这一节就简单的介绍一下程序怎么用,配置就略过啦。

创建Lua虚拟机

复制代码 代码如下:

lua_State *lua_state = luaL_newstate();

加载Lua库

复制代码 代码如下:

static const luaL_Reg lualibs[] =
    {
        {"base", luaopen_base},
        {"io", luaopen_io},
        {NULL, NULL}
    };
    const luaL_Reg *lib = lualibs;
    for(; lib->func != NULL; lib++)
    {
        luaL_requiref(lua_state, lib->name, lib->func, 1);
        lua_pop(lua_state,1);
    }

运行Lua脚本

复制代码 代码如下:

std::string scriptPath = FileUtils::getInstance()->fullPathForFilename("hello.lua");
int status = luaL_loadfile(lua_state, scriptPath.c_str());
std::cout << " return: " << status << std::endl;
int result = 0;
if(status == LUA_OK)
{
    result = lua_pcall(lua_state, 0, LUA_MULTRET, 0);
}
else
{
    std::cout << " Could not load the script." << std::endl;
}

这里我们使用的是luaL_loadfile而不是之前的luaL_dofile,其实luaL_dofile只是一个宏定义:

复制代码 代码如下:

#define luaL_dofile(L, fn) \
    (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))

我们先调用luaL_loadfile可以判断Lua脚本是否加载成功,然后再调用lua_pcall来执行Lua脚本。

C/C++调用Lua函数

首先,我们在hello.lua里面定义一个lua函数:

复制代码 代码如下:

-- add two numbers
function add ( x, y )
    return x + y
end

Lua的函数定义是以function为keyword,然后以end结尾,同时它的参数是没有形参类型的,另外,Lua的函数可以返回多个值。不过我们这里只返回了一个值。

接下来,让我们看看如果在C++程序里面调用这个函数:

复制代码 代码如下:

int luaAdd(lua_State *lua_state , int x, int y)
{
    int sum;
    //获取lua里面的add函数并把它放到lua的栈顶
    lua_getglobal(lua_state, "add");
    //往lua栈里面压入两个参数
    lua_pushnumber(lua_state, x);
    lua_pushnumber(lua_state, y);
    //调用lua函数,这里的2是参数的个数,1是返回值的个数
    lua_call(lua_state, 2, 1);
    //从栈顶读取返回值,注意这里的参数是-1
    sum = lua_tointeger(lua_state, -1);
    //最后我们把返回值从栈顶拿掉
    lua_pop(lua_state, 1);
    return sum;
}

然后,我们就可以在程序里面调用它了:

复制代码 代码如下:

std::cout<< "2 + 1= " << luaAdd(lua_state,4,1)<<std::endl;

注意这个方法调用要在lua_pcall调用之后。

操作Lua全局变量

C++里面获取Lua全局变量的值

首先,我们在hello.lua里面定义一个全局变量

复制代码 代码如下:

myname = "子龙山人"

然后我们在C++里面访问它:

复制代码 代码如下:

lua_getglobal(lua_state, "myname");
std::string myname = lua_tostring(lua_state, -1);
lua_pop(lua_state, 1);
std::cout<<"Hello: "<<myname<<std::endl;

这一次我们又是通过lua_getglobal来把myname这个全局变量压到lua栈,然后用lua_tostring来取这个值。

C++里面修改Lua全局变量的值

这次我们使用的是lua_setglobal来传递数据给Lua:

复制代码 代码如下:

lua_pushstring(lua_state, "World");
    lua_setglobal(lua_state, "myname");

这时,我们只要在hello.lua的最开始部分,调用print(myname)就可以打印传递进来的值了。

C++传递Table给Lua

复制代码 代码如下:

lua_createtable(lua_state, 2, 0);
    lua_pushnumber(lua_state, 1);
    lua_pushnumber(lua_state, 49);
//    lua_settable(lua_state, -3);
    lua_rawset(lua_state, -3);
    lua_pushnumber(lua_state, 2);
    lua_pushstring(lua_state, "Life is a beach");
//    lua_settable(lua_state, -3);
    lua_rawset(lua_state, -3);
    lua_setglobal(lua_state, "arg");

这里我们传递了一个table给lua,这个table为{49,”Life is a beach”}。Lua table的索引是从1开始的,然后我们在lua脚本里面可以这样子来访问这个table:

复制代码 代码如下:

for i=1,#arg do
    print("      ", i, arg[i])
end

这里的#arg是获得table的长度,然后使用arg[i]来获取table的索引i处的value。

Lua返回多个值给C++

首先是Lua代码:

复制代码 代码如下:

local temp = {9, "hehehej"}
-- temp[1]=9
-- temp[2]="See you space cowboy!"
return temp,9,1

然后是C++代码:

复制代码 代码如下:

std::stringstream str_buf;
    while(lua_gettop(lua_state))
    {
        str_buf.str(std::string());
        str_buf << " ";
        switch(lua_type(lua_state, lua_gettop(lua_state)))
        {
            case LUA_TNUMBER:
                str_buf << "script returned the number: "
                << lua_tonumber(lua_state, lua_gettop(lua_state));
                break;
            case LUA_TTABLE:
                str_buf << "script returned a table";
                break;
            case LUA_TSTRING:
                str_buf << "script returned the string: "
                << lua_tostring(lua_state, lua_gettop(lua_state));
                break;
            case LUA_TBOOLEAN:
                str_buf << "script returned the boolean: "
                << lua_toboolean(lua_state, lua_gettop(lua_state));
                break;
            default:
                str_buf << "script returned an unknown-type value";
        }
        lua_pop(lua_state, 1);
        std::cout << str_buf.str() << std::endl;
    }

最后输出结果为:

复制代码 代码如下:

[C++] Values returned from the script:
 script returned the number: 1
 script returned the number: 9
 script returned a table
[C++] Closing the Lua state

在lua里面return值的顺序是table,9,1,而在C++里面是倒过来的。因为我们是使用栈作为数据结构来传递数据,而栈是先进后出的。

下一篇文章,我们将介绍一下C++调用Lua的Table。

时间: 2024-11-03 23:56:45

Lua教程(二):C++和Lua相互传递数据示例_Lua的相关文章

Lua教程(一):Lua脚本语言介绍_Lua

Lua 是一个扩展式程序设计语言,它被设计成支持通用的过程式编程,并有相关数据描述的设施. Lua 也能对面向对象编程,函数式编程,数据驱动式编程提供很好的支持. 它可以作为一个强大.轻量的脚本语言,供任何需要的程序使用. Lua 以一个用 clean C 写成的库形式提供.(所谓 Clean C ,指的 ANSI C 和 C++ 中共通的一个子集) 作为一个扩展式语言,Lua 没有 "main" 程序的概念:它只能 嵌入 一个宿主程序中工作,这个宿主程序被称作 embedding p

Lua教程(六):编译执行与错误_Lua

1. 编译:     Lua中提供了dofile函数,它是一种内置的操作,用于运行Lua代码块.但实际上dofile只是一个辅助函数,loadfile才是真正的核心函数.相比于dofile,loadfile只是从指定的文件中加载Lua代码块,然后编译这段代码块,如果有编译错误,就返回nil,同时给出错误信息,但是在编译成功后并不真正的执行这段代码块.因此,我们可以将dofile实现为: 复制代码 代码如下:  function dofile(filename)      local f = as

js-两个HTML页面如何传递数据?

问题描述 两个HTML页面如何传递数据? 这是A html页面,通过?的方式将数据传递给B页面这是B html页面,接受到d数据,但是d是name=[][][]:中括号里面数据是我想要的,我该怎么取到这些数据?我这样在页面间传递数据的方法正确吗?求各位大神开导开导小弟啊 解决方案 浏览器支持localStorage可以放缓存里面用到sessionStorage也可以放在sessionStorage里面存储:localStorage.setItem(""temp""J

一起谈.NET技术,在ASP.NET网页间传递数据的五种方法

重点总结 目前为止在ASP.NET网页中传递数据的方式至少有5种: 1.通过查询字符串传递数据. 2.通过HTTP POST传递数据. 3.通过会话状态传递数据. 4.通过源页的公共属性传递数据. 5.通过源页中的控件值传递数据. 到底使用哪种方式来进行数据的传递,这可能受到两方面的影响: 1.页面重定向的方式. 2.源页和目标页是否位于相同的ASP.NET应用程序中. 如果源页和目标页位于不同的ASP.NET应用程序中则只能通过查询字符串和HTTP POST传递数据. 而如果源页和目标页位于相

在ASP.NET网页间传递数据的五种方法

重点总结 目前为止在ASP.NET网页中传递数据的方式至少有5种: 1.通过查询字符串传递数据. 2.通过HTTP POST传递数据. 3.通过会话状态传递数据. 4.通过源页的公共属性传递数据. 5.通过源页中的控件值传递数据. 到底使用哪种方式来进行数据的传递,这可能受到两方面的影响: 1.页面重定向的方式. 2.源页和目标页是否位于相同的ASP.NET应用程序中. 如果源页和目标页位于不同的ASP.NET应用程序中则只能通过查询字符串和HTTP POST传递数据. 而如果源页和目标页位于相

Lua教程(五):C/C++操作Lua数组和字符串示例_Lua

本文将介绍如何在C/C++里面操作Lua的数组和字符串类型,同时还会介绍如何在C/C++函数里面存储Lua状态(registry和upvalue),而registry在使用C/C++自定义类型时非常有用,可以方便地为userdata指定metatable. C/C++操作Lua数组 Lua数组Overview 在Lua里面,数组只不过是key为整数的table而已.比如一个table为array = {12,"Hello", "World"},它是一个数组,可以用下

Lua教程(一):在C++中嵌入Lua脚本_Lua

本系列教程主要介绍如何在C/C++程序里面嵌入Lua脚本,我打算从以下几个方面来介绍: 1.如何在C/C++里面嵌入Lua脚本 2.Lua访问C/C++数据结构(这里面要介绍类,结构体,函数,变量,枚举等数据类型在lua里面如何访问) 3.C/C++访问Lua的数据,主要是基本数据类型,函数和Table 4.Cocos2D-X里面的Lua绑定(含自动绑定与手动绑定) 5.Cocos2D-x里面Lua和C/C++相互调用 6.Cocos2D-x里面Lua和Java相互调用 7.Cocos2D-x里

Lua教程(四):在Lua中调用C语言、C++的函数_Lua

本教程将介绍如何在Lua里面调用c/c++函数. 在Lua里面调用c/c++函数其实是比较简单,本文将通过两个示例演示具体的做法:一个是求平均数,另一个是打印lua函数的一些参数信息. 最后,本文会介绍如何把这两个函数定义成一个模块,这样lua代码里面就可以不再使用全局的名字空间了. 前言 当我们需要在Lua里面调用c/c++函数时,所有的函数都必须满足以下函数签名: 复制代码 代码如下: typedef int (*lua_CFunction) (lua_State *L); 换句话说,所有的

Lua教程(一):简介、优势和应用场景介绍_Lua

一.简介: Lua作为目前最为流行的.免费轻量级嵌入式脚本语言,在很多工业级的应用程序中被广泛应用,如Adobe's Photoshop,甚至是在一些著名的游戏程序中也被大量使用,如星际.不仅如此,由于Lua具备很多特殊的优点,如语法简单(基于过程).高效稳定(基于字节码).可以处理复杂的数据结构.动态类型.以及自动内存管理(基于垃圾收集)等,因此在很多嵌入式设备和智能移动设备中,为了提高程序的灵活性.扩展性和高可配置性,一般都会选择Lua作为它们的脚本引擎,以应对各种因设备不同而带来的差异.