原帖地址:
http://www.cnblogs.com/sevenyuan/p/4511808.html
lua和c++的交互就是通过一个无处不在的栈来实现的,此图如此传神啊!
#include <iostream>
#include <string.h>
using namespace std;
extern "C"
{
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
}
void main()
{
//1.创建一个state
lua_State *L = luaL_newstate();
//2.入栈操作
lua_pushstring(L, "I am so cool~");
lua_pushnumber(L,20);
//3.取值操作
if( lua_isstring(L,1)){ //判断是否可以转为string
cout<<lua_tostring(L,1)<<endl; //转为string并返回
}
if( lua_isnumber(L,2)){
cout<<lua_tonumber(L,2)<<endl;
}
//4.关闭state
lua_close(L);
return ;
}
我们可以用push*的方式将我们的数据,或者说是c++中的数据送到栈里面去。在上面的示例中,我们push了两个数据到lua的栈里面去,一个string = “I am so cool”,另一个是一个数字“20”。然后我们用lua_is*将这些数据取出来,并切输出到显示器。
不过在进行所有的这些操作之前,我们必须要手动建立一个lua栈,这是通过lua_newstate()完成的。这个函数返回指向这个栈栈顶的指针。
示例:如何读取lua中的数据到cpp中来,只要完成了这个,就可以用lua做我们的配置文件了,感觉比xml什么的牛多了。
这是我们的lua代码,里面存储了一些数据,如下:
str = "I am so cool"
tbl = {name = "shun", id = 20114442}
function add(a,b)
return a + b
end
读取这个lua文件中的数据的c++代码如下:
#include <iostream>
#include <string.h>
using namespace std;
extern "C"
{
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
}
void main()
{
//1.创建Lua状态
lua_State *L = luaL_newstate();
if (L == NULL)
{
return ;
}
//2.加载Lua文件
int bRet = luaL_loadfile(L,"hello.lua");
if(bRet)
{
cout<<"load file error"<<endl;
return ;
}
//3.运行Lua文件
bRet = lua_pcall(L,0,0,0);
if(bRet)
{
cout<<"pcall error"<<endl;
return ;
}
//4.读取变量
lua_getglobal(L,"str");
string str = lua_tostring(L,-1);
cout<<"str = "<<str.c_str()<<endl; //str = I am so cool~
//5.读取table
lua_getglobal(L,"tbl");
lua_getfield(L,-1,"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 ;
}
如果这些代码出现链接错误,说明没有配置好lua的lib和dll文件的位置。
我们可以通过调用lua_pcall(L,0,0,0)来清空lua的堆栈。
获取lua错误堆栈中的信息:
原帖地址:
http://www.cnblogs.com/meteoric_cry/p/3665258.html
lua_getglobal(tolua_S, "debug");
lua_getfield(tolua_S, -1, "traceback");
int iError = lua_pcall( tolua_S,//VMachine
0,//Argument Count
1,//Return Value Count
0);
const char* sz = lua_tostring(tolua_S, -1);
CCLog(sz);
在lua中用c++的函数
原帖地址:
http://www.cnblogs.com/Zackzhang/p/5094942.html
在lua中调用c++的函数有两种方法,一是将c函数作为应用程序的一部分,二是将c函数作为lua的一个模块。
怎么理解第一种方式呢?我们的c代码里是有main函数的,我们将我们需要在lua中调用的函数在main函数里注册一下,然后在lua里直接调用。第二种方式是将我们的函数弄到一个dll里面(windows平台是dll,unix中是so),然后通过lua的require关键字把这个dll作为一个模块包含进来,然后就可以愉快的使用c++中的函数了。
在lua中调用c函数,那么c函数需要的参数自然就是从lua中传过去的了。
上代码:
#include <stdio.h>
#include <string.h>
#include "lua.hpp"
#include "lauxlib.h"
#include "lualib.h"
//待注册的函数
//该函数必须以c的形式被导出,因此extern "C"是必须的
extern "C" int average(lua_State* L)
{
double sum = 0;
int num = lua_gettop(L);//获取参数的个数,因为栈顶的正数代表的正是参数的个数
for (int i = 1; i <= num; i++)
{
sum += lua_tonumber(L, i);//将栈中的元素挨个取出并相加
}
//在上面的过程执行之后,我们将平均值入栈,作为返回值
lua_pushnumber(L, sum / num);
return 1;//返回返回值的个数,通知lua应该从栈里面取几个值作为返回结果,因为lua是支持多重返回值的
}
extern "C" int Communicate(lua_State* L)
{
const char* name = lua_tostring(L, 1);//从lua中获取字符串
printf("Hello %s\n", name);
printf("I'm in C,I send a message to you");
lua_pushstring(L, "this message from C");
return 1;
}
//luaL_Reg结构体的第一个字段为字符串,在注册时用于通知Lua该函数的名字。
//第一个字段为C函数指针。
//结构体数组中的最后一个元素的两个字段均为NULL,用于提示Lua注册函数已经到达数组的末尾。
static luaL_Reg cMethods[] = {
{"average",average},
{"Communicate ",Communicate },
{NULL,NULL}
};
//该C库的唯一入口函数。其函数签名等同于上面的注册函数。见如下几点说明:
//1. 我们可以将该函数简单的理解为模块的工厂函数。
//2. 其函数名必须为luaopen_xxx,其中xxx表示library名称。Lua代码require "xxx"需要与之对应。
//3. 在luaL_register的调用中,其第一个字符串参数为模块名"xxx",第二个参数为待注册函数的数组。
//4. 需要强调的是,所有需要用到"xxx"的代码,不论C还是Lua,都必须保持一致,这是Lua的约定,
// 否则将无法调用。
extern "C" __declspec(dllexport)
int luaopen_Mydll(lua_State* L)
{
const char* libName = "Mydll";
luaL_register(L, libName, cMethods);
return 1;
}
按下vs中的F7执行编译,然后就可以得到我们要用的dll了。
hello.lua的写法
require "Mydll" --引入包
--在调用时,必须是package.function
print(Mydll.average(1.0,2.0,3.0,4));
print(Mydll.Communicate("Zack"));