您的位置:首页 > 编程语言 > Lua

c++和lua

2017-01-15 22:26 141 查看
原帖地址:

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++代码如下:

4000

#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"));
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: