上一篇我们搭建好了整个的项目环境,现在,我们一起探索一下如何将lua寄宿到C++中。

宿主的实现

我们在LuaWithCPPTest项目下,查看Source.cpp代码如下:

#include <iostream>

#include <fstream>

#include <string>

using namespace std;

 

extern "C"

{

    #include <lua.h>

    #include <lauxlib.h>

    #include <lualib.h>

};

 

void TestLua();

 

int main()

{

    TestLua();

    return 0;

}

 

void TestLua()

{

    lua_State *L = luaL_newstate();

    luaopen_base(L); //

    luaopen_table(L); //

    luaopen_package(L); //

    luaopen_io(L); //

    luaopen_string(L); //

 

    luaL_openlibs(L); //打开以上所有的lib

 

    string str;

 

 

    while (true)

    {

        cout << "请输入Lua代码:" << endl;

        getline(cin, str, '\n');

        if (luaL_loadstring(L, str.c_str())

            || lua_pcall(L, 0, 0, 0) )

        {

            const char * error = lua_tostring(L, -1) ;

            cout << string(error) << endl;

        }

    }

 

    lua_close(L);

}

其中,被extern "C"包起来的是lua的主要函数的声明。在C++中,每个嵌入的lua的生命周期与各自的lua_State对象一一对应。通过luaL_newstate()方法,我们便创建了一个lua解释器。随后的几个luaopen_*方法,都是获取相应lua库的使用权,最后通过luaL_openlibs打开所有的有使用权的lua标准库。一切准备就绪后,我们开始接收输入。

我们通过luaL_loadstring,将所有代码读入lua,并且检查代码是否有语法错误。然后通过lua_pcall,运行代码,将所有的全局变量保存在_G中。通过读取、运行这两步,我们就建立起一个自己的lua解释器了。

将lua作为配置文件

从文件读取lua代码,流程与之前的示例一样,仅是将luaL_loadstring()换成luaL_loadfile()即可。代码如下: 

string str;

while (true)

{

    cout << "输入lua文件路径:" << endl;

    getline(cin, str, '\n');

    if (luaL_loadfile(L, str.c_str())

        || lua_pcall(L, 0, 0, 0) )

    {

        const char * error = lua_tostring(L, -1) ;

        cout << string(error) << endl;

        return;

    }

 

}

现在,我们在lua中定义变量,并且赋值。然后在c++中取值,运算出结果。在lua文件中,内容如下:

在c++中,我们获取a,b两个变量的值,然后相加,算出结果:

#include <iostream>

#include <fstream>

#include <string>

using namespace std;

 

extern "C"

{

 

#include <lua.h>

#include <lauxlib.h>

#include <lualib.h>

};

 

void TestLua();

 

int main()

{

    TestLua();

    return 0;

}

 

void TestLua()

{

    lua_State *L = luaL_newstate();

    luaopen_base(L); //

    luaopen_table(L); //

    luaopen_package(L); //

    luaopen_io(L); //

    luaopen_string(L); //

 

    luaL_openlibs(L); //打开以上所有的lib

 

    string str;

    while (true)

    {

        cout << "输入lua文件路径:" << endl;

        getline(cin, str, '\n');

        if (luaL_loadfile(L, str.c_str())

            || lua_pcall(L, 0, 0, 0) )

        {

            const char * error = lua_tostring(L, -1) ;

            cout << string(error) << endl;

            return;

        }

        else

        {

            break;

        }

 

    }

 

    int a = 0;

    int b = 0;

 

    // 获取a的值

    lua_getglobal(L, "a");

    if (!lua_isnumber(L, -1))

    {

        cout << "-2 error" << lua_isnumber(L, -1) << lua_isnumber(L, -1) << endl;

        return ;

    }

 

    a = lua_tonumber(L, -1);

 

    // 获取b的值

    lua_getglobal(L, "b");

    if (!lua_isnumber(L, -1))

    {

        cout << "-1 error" << endl;

        return ;

    }

    

    b = lua_tonumber(L, -1);

 

    cout << "a = " << a << " b = " << b << endl;

    cout << "a + b = " << a + b << endl;

 

    lua_close(L);

 

}

最后的得到结果如下:

将文件载入lua后,我们通过lua_getglobal()方法,将想要获得的lua值放入栈顶(栈为何物,下篇分析),然后用lua_isnumber(L, –1)来检测栈顶的元素是否是number,若果是,调用lua_tonumber(L,-1)来将栈顶的值传递给c++变量,整个流程为:1、将欲获得的lua值放入栈中;2、检测栈中的值是否ok;3、取出栈中的值。lua有一系列的lua_is*()来检测栈中的值是否是相应的*类型,相应的,也有一系列的lua_to*()来取值:

总结

写这篇的时候,我内心比较纠结,在内容的深度上把握不准,最终我的定位是:这系列只描述两者之间交互的步骤、方式,不深入去描述原理。原因很简单,因为我的水平有限。在自己水平不足的情况下,去描述c++与lua内在的交互原理,会误导人。我目前的大纲是:第一篇搭建环境;第二篇描述C++调用lua的一些数据;第三篇讲解C++与lua之间的栈,主要还是偏重C++代码调用lua代码。第四篇描述lua如何调用c++代码。第五篇介绍工具tolua++。以上。

C++与Lua交互(二)的更多相关文章

  1. C++与Lua交互(四)

    引言 通过前几篇,我们已经对Lua的C API有了一定的了解,如lua_push*.lua_is*.lua_to*等等.用C++调用Lua数据时,我们主要运用lua_getglobal与lua_pus ...

  2. C++与Lua交互(一)

    引言 之前做手游项目时,客户端用lua做脚本,基本所有游戏逻辑都用它完成,玩起来有点不爽,感觉"太重"了.而我又比较偏服务端这边(仅有C++),所以热情不高.最近,加入了一个端游项 ...

  3. C++与Lua交互之配置&交互原理&示例

    |Lua 简介 Lua 是一种轻量小巧的脚本语言,也是号称性能最高的脚本语言,它用C语言编写并以源代码形式开放. 某些程序常常需要修改内容,而修改的内容不仅仅是数据,更要修改很多函数的行为. 而修改函 ...

  4. Cocos 2d-X Lua 游戏添加苹果内购(二) OC和Lua交互代码详解

    这是第二篇 Cocos 2d-X Lua 游戏添加苹果内购(一) 图文详解准备流程 这是前面的第一篇,详细的说明了怎样添加内购项目以及填写银行信息提交以及沙盒测试员的添加使用以及需要我们注意的东西,结 ...

  5. 教程二 网页和lua交互修改openwrt

    硬件 http://zhan.renren.com/h5/entry/3602888498044209332 GL-iNet 1 首先安装 webserver之lighttpd  ,openwrt自带 ...

  6. Win32下 Qt与Lua交互使用(二):在Lua脚本中使用Qt类

    话接上篇.成功配置好Qt+Lua+toLua后,我们可以实现在Lua脚本中使用各个Qt的类.直接看代码吧. #include "include/lua.hpp" #include ...

  7. 最优雅的C++跟lua交互.

    我先来吐槽一下我们这个项目. 我是做手机游戏的, cocos2dx引擎, lua编码. 这本来是一件很欢快的事情, 因为不用接触C++. C++写久了的人写lua, 就会感觉任督二脉被打通了, 代码写 ...

  8. vs2013如何在C++中调用Lua(二)

    Lua学习笔记 vs2013如何在C++中调用Lua (此为转载教程) 本人试过完全可行 一.准备工作 1.下载Lua源码,地址:http://www.lua.org/download.html(我用 ...

  9. C++与Lua交互(三)

    通过上一篇的热身,我们对C++调用lua变量有了一个认识,现在让我们再深入一点,去探索一下如何调用lua的函数.表. Lua与宿主通讯的关键--栈 lua是个动态脚本语言,它的数据类型如何映射到C++ ...

随机推荐

  1. 数据库SQLite应用

    1.导入SQLite库和头文件 #import <sqlite3.h> 2.打开数据库,如果在打开的时候遇到了问题,则关闭它并抛出一个断言错误. sqlite3 * database; i ...

  2. Maven学习小结(四 聚合与继承)

    1.聚合 一次构建多个项目模块. 2.继承 为了消除重复,把很多相同的配置提取出来,例如groupid和version: 2.1 Maven中可以继承的POM元素 groupId :项目组 ID ,项 ...

  3. 为什么arcgis里,鼠标的图标都变成放大镜不能用了

    做作业做到一半,鼠标的图标就只有放大镜了,不管是点箭头还是作图工具都没用,手抓的也没用,只剩下放大镜的功能和图标了,这是怎么一回事啊?种情况我碰到过几次,具体原因不清楚,但是解决方法是有的:把你的数据 ...

  4. Debian 7 安装使用 Virtualbox及增强功能

    一.安装virtualbox 可以从源里安装 sudo apt-get install virtualbox 也可以下载最新版安装 https://www.virtualbox.org/wiki/Do ...

  5. iOS 成员变量,实例变量,属性变量的区别,联系

    在ios第一版中: 我们为输出口同时声明了属性和底层实例变量,那时,属性是oc语言的一个新的机制,并且要求你必须声明与之对应的实例变量,例如: 注意:(这个是以前的用法) @interface MyV ...

  6. [转]HTML accesskey 属性

    本文转自:http://www.dreamdu.com/xhtml/attribute_accesskey/ 17.2. HTML accesskey 属性 accesskey 属性  --  代表链 ...

  7. VIJOS P1540 月亮之眼

    [题目大意] 有多个珠子,给出部分珠子之间的相对上下位置和间距,问你这些珠子在满足给出的条件下,是否能把珠子排列在一条竖直直线上,如果能,求出每个珠子距离最高的珠子的距离,珠子的位置可重叠. [分析] ...

  8. oracle中的sql%rowcount

    sql%rowcount用于记录修改的条数,就如你在sqlplus下执行delete from之后提示已删除xx行一样,这个参数必须要在一个修改语句和commit之间放置,否则你就得不到正确的修改行数 ...

  9. Wince 对话框程序设计

    如何编程实现wince下“打开文件夹对话框”呢?这里就要涉及到下面要分析的知识了,对话框是一种特殊的窗口,它在wince 作为应用程序和程序使用者之间的交流窗口,通过显示和获取信息使人们的交流更加方便 ...

  10. 轻松学习Ionic (四) 修改应用图标及添加启动画面(更新官方命令行工具自动生成)

    由于Ionic更新了命令行工具,以后修改应用图标和添加启动画面就简单了,最新方法见最下方:   应用图标:   1.在整个项目所在文件夹下创建res文件夹,里边再分别创建两个文件夹android和io ...