C++ 和lua交互学习的三个例子
2017-04-22 15:53
676 查看
C++ 和 Lua 交互学习
Lua简介及安装
Lua的优点:
最快的脚本语言可以编译调试
与C/C++结合容易
Lua是对性能有要求的必备语言
Lua的应用:
游戏的任务脚本,后端服务器AlphaGo: C++ + lua实现
视频服务器、入侵检测脚本、防火墙脚本
Lua的官网: http://www.lua.org/versions.html
5.1 较快5.3 性能有些下降
Lua的安装
C++ 调用 lua之前需要先安装lua,可以下载lua的源码进行编译安装,在CentOS平台下,还可以直接使用yum安装,CentOS默认使用lua的版本是5.1的版本,如:yum install lua lua-devel
Lua 的基本概念
Lua的基本数据类型:
nil:表示没有数据,当希望释放数据时,直接将nil赋值给该变量即可boolean:在lua中除了false和nil为假,其他都为真,true|false
numbers类型:
lua中没有整数,都是浮点数运算,对应C中的double;
新版本的lua是基于64位的整型,5.1暂不支持
可以tonumber转换格式
string类型:
tostring转换格式
[[]]多行字符串赋值
与C一样的转义
通过..实现字符串的拼接,且可以直接拼接整型,注意不能拼接nil的变量
string.len(str), 获取字符串长度
string.sub(str,3,5),获取子字符串
local b,e = string.find(),查找,支持正则
string.gsub(),替换,不改变原值,返回替换后的值,支持正则
lua的下标是从1开始的,和matlab相同
Lua和C++的交互
调用C++中的函数, 通过堆栈交互包含头文件
extern "C" { #include <lua.h> #include <lualib.h> #include <lauxlib.h> }
编译
g++ -o XX XX.cpp -llua -ldl
第一个例子
C++代码#include <iostream>
using namespace std;
extern "C" { #include <lua.h> #include <lualib.h> #include <lauxlib.h> }
int main()
{
lua_State *L = lua_open();
luaopen_base(L);
luaopen_string(L);
luaopen_table(L);
// 加载 lua 文件
if ( luaL_loadfile(L, "main.lua") )
{
const char* error = lua_tostring(L, -1);
cout << "lua load error: "<< error << endl;
return -1;
}
// 执行 lua 文件
if ( lua_pcall(L, 0, 0, 0) )
{
const char* error = lua_tostring(L, -1);
cout << "lua call error: "<< error << endl;
return -1;
}
getchar();
return 0;
}
lua代码
print("hello word")
第二个列子
C++ code#include <iostream>
using namespace std;
extern "C" { #include <lua.h> #include <lualib.h> #include <lauxlib.h> }
// 开放函数给lua调用,并获取 Lua 传递的三个参数,普通参数
int CTest(lua_State* L)
{
cout << "enter in CTest" << endl;
size_t len;
const char* name = lua_tolstring(L, 1, &len);
cout << "Lua name: " << name << endl;
int age = lua_tonumber(L, 2);
cout << "Lua age: " << age << endl;
bool bIs = lua_toboolean(L, 3);
cout << "Lua bool: " << bIs << endl;
return 0;
}
// 开放函数给lua调用,并获取 Lua 传递的表参数,按索引获取表参数
int CTestArray(lua_State* L)
{
cout << "In CTestArray" << endl;
int arrLen = luaL_getn(L,1); // 获取表的长度
cout << "Table size: " << arrLen << endl;
for (int i = 1; i <= arrLen; i++)
{
lua_pushnumber(L, i); // 2
lua_gettable(L,1); // pop index and push table[i]
size_t iSize = 0;
cout << lua_tolstring(L, -1, &iSize) << endl;
lua_pop(L, 1);
}
return 0;
}
// 开放函数给lua调用,并获取 Lua 传递的表参数,按键值获取表参数
int CTestKeyVal(lua_State* L)
{
cout << "In CTestKeyVal" << endl;
lua_pushnil(L);
while(lua_next(L,1) != 0)
{
cout << "key=" << lua_tostring(L,2) << ", ";
cout << "value=" << lua_tostring(L,-1) << endl;
lua_pop(L,1);
}
return 0;
}
// 开放函数给lua调用,并判断获取的参数是否是希望的类型
int CTestKeyVal_type(lua_State* L)
{
// method1: type check
luaL_checktype(L, 1, LUA_TTABLE);
// method2: type check
if (lua_type(L,2) != LUA_TNUMBER)
{
cout << "para 2 is not a number" << endl;
}
cout << "In CTestKeyVal" << endl;
lua_getfield(L,1, "name");
cout << "name: " <<lua_tostring(L,-1) <<endl;
return 0;
}
// 开放函数给lua调用,C++ 返回一个普通的字符串
int CTestRetOne(lua_State* L)
{
lua_pushstring(L, "return a string value");
return 1;
}
// 开放函数给lua调用,C++ 返回一个表
int CTestRetTable(lua_State* L)
{
lua_newtable(L); // create new table
lua_pushstring(L, "name"); // push key
lua_pushstring(L, "xiaominmin");// pusn value
lua_settable(L, -3);// write key and value into table
lua_pushstring(L, "age");
lua_pushnumber(L, 29);
lua_settable(L, -3);
return 1;
}
int main()
{
lua_State *L = lua_open();
luaopen_base(L);
luaopen_string(L);
luaopen_table(L);
// 注册开发的函数给lua
lua_register(L, "CTest", CTest);
lua_register(L, "CTestArray", CTestArray);
lua_register(L, "CTestKeyVal", CTestKeyVal);
lua_register(L, "CTestKeyVal_type", CTestKeyVal_type);
lua_register(L, "CTestRetOne", CTestRetOne);
lua_register(L, "CTestRetTable", CTestRetTable);
if ( luaL_loadfile(L, "main.lua") )
{
const char* error = lua_tostring(L, -1);
cout << "lua load error: "<< error << endl;
return -1;
}
if ( lua_pcall(L, 0, 0, 0) )
{
const char* error = lua_tostring(L, -1);
cout << "lua call error: "<< error << endl;
return -1;
}
getchar();
return 0;
}
lua code
-- 调用 CTest,并传递三个普通参数 CTest("Lua string",123, true) -- 调用CTestArray,并传递带索引的表 local arr = {"A001","A002","A003", "A004"} CTestArray(arr) -- 调用 CTestKey,并传递键值表 local arr = {name="xiaoming", age="32",id="007"} local size = "s108" CTestKeyVal(arr) -- 调用 CTestKey_type,并传递键值表,判读参数类型是否是期望的类型 local arr = {name="xiaoming", age="32",id="007"} local size = "s108" CTestKeyVal_type(arr, size) -- 调用 CTestRetOne,并打印C++返回的值 local ret = CTestRetOne() print ("ret = "..ret) -- 调用 CTestRetTable,并打印C++的表 local ret = CTestRetTable() print ("name = "..ret["name"]) print ("age = "..ret["age"])
第三个例子
C++ code#include <iostream>
using namespace std;
extern "C" { #include <lua.h> #include <lualib.h> #include <lauxlib.h> }
int main()
{
lua_State *L = lua_open();
// 打开需要用到的lua的库
luaopen_base(L);
luaopen_string(L);
luaopen_table(L);
/* lua脚本启动之前,给lua脚本设置全局变量 */
// 设置lua的全局变量,hello = test (key = value)
lua_pushstring(L, "hello");
lua_setglobal(L,"test");
// 向 lua 中传递一个表,同例子2中的返回一个表给lua
lua_newtable(L); // create a table
lua_pushstring(L, "name"); // key
lua_pushstring(L, "xiaoming"); // value
lua_settable(L, -3);
lua_pushstring(L, "age"); // key
lua_pushnumber(L, 20); // value
lua_settable(L, -3);
lua_setglobal(L, "person"); // write value to table
if ( luaL_loadfile(L, "main.lua") )
{
const char* error = lua_tostring(L, -1);
cout << "lua load error: "<< error << endl;
return -1;
}
if ( lua_pcall(L, 0, 0, 0) )
{
const char* error = lua_tostring(L, -1);
cout << "lua call error: "<< error << endl;
return -1;
}
// C++ 获取lua中的普通全局变量
lua_getglobal(L, "width");
int width = lua_tonumber(L, -1);
lua_pop(L, 1); // 注意要清lua堆栈
cout << "width: " << width << endl;
// C++ 获取lua中的表全局变量
lua_getglobal(L, "conf");
lua_getfield(L, -1, "titlename");
cout << "titlename: " << lua_tostring(L,-1) << endl;
lua_pop(L,1);
lua_getfield(L, -1, "height");
cout << "height: " << lua_tonumber(L, -1) << endl;
lua_pop(L, 1);
// C++ 调用 lua中的名为 event的函数,无参数无返回值
cout<< "stack top is " << lua_gettop(L) << endl;
lua_getglobal(L, "event");
if ( lua_pcall(L, 0, 0, 0) != 0)// 无参数,无返回值,无回调函数
{
cout << "call event failed " << lua_tostring(L, -1)<< endl;
lua_pop(L, 1);
}
cout<< "stack top is " << lua_gettop(L) << endl;
// C++ 调用 lua中的名为 ferror和event2 的函数,有参数有返回值
cout<< "stack top is " << lua_gettop(L) << endl;
int errfun = lua_gettop(L);
lua_getglobal(L, "ferror");
errfun++;
lua_getglobal(L, "event2");
lua_pushstring(L, "key");
if ( lua_pcall(L, 1, 1, errfun) != 0)// 一个参数,一个返回值,回调函数errfun
{
cout << "call event failed " << lua_tostring(L, -1)<< endl;
lua_pop(L, 1);
}
else
{
cout << "Lua return: " << lua_tostring(L, -1) << endl;
lua_pop(L, 1);
}
lua_pop(L, 1);
cout<< "stack top is " << lua_gettop(L) << endl;
// C++ 调用 lua中的名为 ferror和event3 的函数,有表参数和表返回值
cout<< "stack top is " << lua_gettop(L) << endl;
int errfun1 = lua_gettop(L);
lua_getglobal(L, "ferror");
errfun1++;
lua_getglobal(L, "event3");
lua_pushstring(L, "key");
lua_newtable(L);
lua_pushstring(L,"name");
lua_pushstring(L, "xiaomingming");
lua_settable(L, -3);
if ( lua_pcall(L, 2, 1, errfun) != 0) // 两个参数,一个返回值,回调函数errfun
{
cout << "call event failed " << lua_tostring(L, -1)<< endl;
lua_pop(L, 1);
}
else
{
//cout << "Lua return: " << lua_tostring(L, -1) << endl;
lua_getfield(L, -1, "id");
cout << "Lua return id: " << lua_tonumber(L, -1) << endl;
lua_pop(L,1);
lua_getfield(L, -1, "age");
cout << "lua return age: " << lua_tonumber(L, -1) << endl;
lua_pop(L, 1);
lua_pop(L, 1);
}
lua_pop(L, 1);
cout<< "stack top is " << lua_gettop(L) << endl;
lua_close(L);
return 0;
}
lua code
-- Lua的全局变量,供C++使用 width=1920 conf = { titlename = "first lua", height = 1080 } -- 打印C++设置的全局变量,普通变量 print("C++ test: ".. test) -- 打印C++设置的全局变量,表 for k,v in pairs(person) do print(k.."=>"..v) end -- C++ 调用 lua函数并传递普通参数,lua函数有返回值 function ferror(e) print("lua error: "..e) return "lua change error" end -- C++ 调用 lua函数,无参数,lua函数无返回值 function event() print("C++ call lua function.") end -- C++ 调用 lua函数并传递普通参数,lua函数有返回值 function event2(e) print("C++ call lua function event 1.") print(e) return "Lua renturn a string" end -- C++ 调用 lua函数并传递表参数,lua函数返回表参数 function event3(e, obj) print("C++ call lua function event 1.") print(e) print (obj.name) local re = {id=123, age=29} return re end
相关文章推荐
- 通过例子学习Lua(5) ---- Lua与C交互入门
- Lua和C++交互 学习记录之三:全局值交互
- 通过例子学习Lua(6)----C/C++中用Lua函数
- Lua和C++交互 学习记录之九:在Lua中以面向对象的方式使用C++注册的类
- Lua和C++交互api学习
- Lua和C++交互 学习记录之一:C++嵌入脚本
- Lua和C++交互 学习记录之七:C++全局函数注册为Lua模块
- Lua和C++交互 学习记录之五:全局数组交互
- 通过例子学习Lua(6)--C/C++中用Lua函数
- Lua和C++交互 学习记录之二:栈操作
- 通过例子学习Lua(6) ---- C/C++中用Lua函数(转)
- Lua和C++交互 学习记录之六:全局函数交互
- cocos2d-x学习笔记(十一)c++与lua交互回调函数的处理
- 通过例子学习Lua(5) ---- Lua与C交互入门 (转)
- Lua和C++交互 学习记录之四:全局table交互
- C/C++与Lua交互(C实现的Lua编译器的例子)
- 通过例子学习Lua(5)--Lua与C的交互
- Lua和C++交互 学习记录之八:C++类注册为Lua模块
- 通过例子学习Lua(6)--C/C++中用Lua函数
- 通过例子学习lua-3