C++与Lua交互(二)
上一篇我们搭建好了整个的项目环境,现在,我们一起探索一下如何将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交互(二)的更多相关文章
- C++与Lua交互(四)
引言 通过前几篇,我们已经对Lua的C API有了一定的了解,如lua_push*.lua_is*.lua_to*等等.用C++调用Lua数据时,我们主要运用lua_getglobal与lua_pus ...
- C++与Lua交互(一)
引言 之前做手游项目时,客户端用lua做脚本,基本所有游戏逻辑都用它完成,玩起来有点不爽,感觉"太重"了.而我又比较偏服务端这边(仅有C++),所以热情不高.最近,加入了一个端游项 ...
- C++与Lua交互之配置&交互原理&示例
|Lua 简介 Lua 是一种轻量小巧的脚本语言,也是号称性能最高的脚本语言,它用C语言编写并以源代码形式开放. 某些程序常常需要修改内容,而修改的内容不仅仅是数据,更要修改很多函数的行为. 而修改函 ...
- Cocos 2d-X Lua 游戏添加苹果内购(二) OC和Lua交互代码详解
这是第二篇 Cocos 2d-X Lua 游戏添加苹果内购(一) 图文详解准备流程 这是前面的第一篇,详细的说明了怎样添加内购项目以及填写银行信息提交以及沙盒测试员的添加使用以及需要我们注意的东西,结 ...
- 教程二 网页和lua交互修改openwrt
硬件 http://zhan.renren.com/h5/entry/3602888498044209332 GL-iNet 1 首先安装 webserver之lighttpd ,openwrt自带 ...
- Win32下 Qt与Lua交互使用(二):在Lua脚本中使用Qt类
话接上篇.成功配置好Qt+Lua+toLua后,我们可以实现在Lua脚本中使用各个Qt的类.直接看代码吧. #include "include/lua.hpp" #include ...
- 最优雅的C++跟lua交互.
我先来吐槽一下我们这个项目. 我是做手机游戏的, cocos2dx引擎, lua编码. 这本来是一件很欢快的事情, 因为不用接触C++. C++写久了的人写lua, 就会感觉任督二脉被打通了, 代码写 ...
- vs2013如何在C++中调用Lua(二)
Lua学习笔记 vs2013如何在C++中调用Lua (此为转载教程) 本人试过完全可行 一.准备工作 1.下载Lua源码,地址:http://www.lua.org/download.html(我用 ...
- C++与Lua交互(三)
通过上一篇的热身,我们对C++调用lua变量有了一个认识,现在让我们再深入一点,去探索一下如何调用lua的函数.表. Lua与宿主通讯的关键--栈 lua是个动态脚本语言,它的数据类型如何映射到C++ ...
随机推荐
- apicloud+融云实现即时通讯
请尊重作者的辛勤劳动!!! 使用apicloud开发已经快2个月了,起初的目的就是为了实现安卓和苹果的兼容,属于一个试验项目,究竟apicloud是否能够满足公司的要求?最 终看来还是不错的,使用ap ...
- mysql 5.1 到 mysql 5.2的出现的索引BTREE问题 use near 'USING BTREE
转自:http://hi.baidu.com/our_poll/item/669c5ce885b33ff1e0a5d4fc 我本机测试是安装的 mysql 5.1 , 但服务器上确是使用的 mysql ...
- INNOBACKUPEX热备MYSQL数据
http://www.databaseclub.com/2014/11/innobackupex/ 1)对MySQL进行全备份1.备份数据 1 innobackupex --user=userna ...
- MongoDB笔记--安装篇
安装MongoDB 第一步:下载安装包:官方下载地址←单击此处,如果是win系统,注意是64位还是32位版本的,请选择正确的版本. 第二步:新建目录“D:\MongoDB”,解压下载到的安装包,找到b ...
- [转]AFNetWorking使用笔记
转载自:http://blog.sina.com.cn/s/blog_719d537e01017x82.html AFNetwork是一个轻量级的网络请求api类库.是以NSURLConnection ...
- MySQL的数据库引擎的类型及区别
MySQL的数据库引擎的类型 你能用的数据库引擎取决于mysql在安装的时候是如何被编译的.要添加一个新的引擎,就必须重新编译MYSQL.在缺省情况下,MYSQL支持三个引擎:ISAM.MYISAM和 ...
- 纯JS操作服务器绑定控件(Repeat)实现表头升降排序
JS实现功能 var obj = function (id) { return "string" == typeof id ? document.getElementById(id ...
- this的分析分支
最近看到这个题目,开始不太理解,但是仔细的看完this之后,觉得懂了一些 function Foo() { getName = function () { alert (1); }; return t ...
- ArcGIS Server 10.2 实战(二)动态修改要素数据的地理处理服务
上一篇<ArcGIS Server 10.2 实战(一)Asp.net MVC与JSON数据妙用实现动态生成要素图层>介绍了如何用JSON转要素的地理处理服务,实现了动态创建点要素并加载到 ...
- Telnet客户端连接服务器,看不见字符,只显示横线
Telnet 窗口看不见字符,只显示小横线 在用telnet连接tomcat服务器的 时候,窗口中不显示字符,显示成一个一个的横线 解决办法: 按住“Ctrl+]” 回车解决问题