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

c++ 与 lua的关系

2015-10-16 11:57 513 查看
脚本语言对于c++等语言存在着许多天然的优势,游戏引擎都需要支持脚本语言,cocos2dx 支持lua、js脚本语言进行开发.主要分析lua与coco2dx引擎中c++的关联。

lua作为脚本语言,经常在游戏开发中使用到. lua的源码是由c实现,能够很好的存活在宿主环境中,所以跟c++的交互实现也很简单。

1、环境搭配(visual studio)

下载lua源码,目录中的存在INSTALL文件指导编译。

windows 由lua.lib lua.exe luac.exe 分别为lua的库,lua的解释器,lua编译器 ,
按照INSTALL的要求,将不同项目需求的源文件加入项目中,根据 exe,lib设置输出配置类型。
在项目中需要使用lua,lua.h lualib.h lauxlib.h luaconf.h 以及库文件即可。

2、c++ 调用 lua 脚本

由于lua是由c实现的所以提供了C API来实现对lua脚本的控制、调用.http://www.lua.org/manual/5.1/manual.html(C
API)

c++调用lua的流程:

1、包含lua.h、lualib.h、lauxlib.h头文件,其中定义了Lua提供的基础函数。

2、若使用c++编译器,c++为支持多态会对函数名跟参数进行处理生成中间函数名,c不会生成中间函数名,出现无法找到函数的实现,链接错误。由于lua是c语言实现所以通过extern "C"{}关键字告诉编译器使用c语言的编译链接形式。

3、通过lua_open()创建一个新的Lua环境(5.2需要使用luaL_newstate来创建lua_open已经废了),返回值为lua_State结构体类型变量,由于Lua库没有定义任何全局变量,所有状态都保存在这个结构体中,所以Lua函数的第一个参数都指向这个结构体变量,能够保存lua环境中的状态。

4、使用luaL_openlibs函数,会在该环境下导入所有的lua标准库。

5、我们要运行lua文件中的将lua文件通过luaL_loadfile函数内部调用lua_load 加载 lua chunk到栈顶,并不运行chunk。

6、lua_pcall(L,0,0,0)实例化chunk.

7、通过lua_getglobal(L,"function_name")把值(函数名称、lua变量名)推送到栈顶。

8、函数带有参数,需要使用lua_push开头后面跟类型名称的函数将对应类型push到栈顶。push是从第一个参数开始(先测试常用的类型,以后了解自定义类型,指针类型)。

9、lua_pcall (lua_State *L, int nargs, int nresults, int msgh)执行先前的function_name的函数,nargs就是函数的参数个数,nresults就是返回值的个数。msg0 栈顶显示原始的出错信息。

10、lua_isnumber(L,-1)判断栈顶是否是数字。若执行成功,栈顶就是数据的返回值。第二个参数为栈的索引值,整数1, 2, 3, 4表示从栈底数起,负数-1,-2,-3,-4表示从栈顶数起。

11、获取返回值lua_tonumber(L,-1). -1代表最后返回的值也是最后压入栈中的。需要将值lua_pop(L,1),弹出N个元素从栈中因为返回值为1则第二个参数为1,函数没有返回值不需要执行该操作。

12、lua_close 释放资源

简单例子

extern "C"

{

#include<lua.h>

#include<lualib.h>

#include<lauxlib.h>

}

#pragma comment(lib,"lualib.lib")

#include <iostream>

using namespace std;

int main()

{

lua_State *L = lua_open();

if (NULL == L)

cout << "create lua failed"<<endl;

luaL_openlibs(L);

if (LUA_ERRFILE ==luaL_loadfile(L,"./test.lua"))

cout << "can't open lua file "<< endl;

lua_pcall(L,0,0,0);

lua_getglobal(L,"hello");

lua_pcall(L,0,0,0);

lua_getglobal(L,"add");

lua_pushnumber(L,10);

lua_pushnumber(L,5);

if (lua_pcall(L,2,2,0) !=0)

cout << lua_tostring(L,-1)<<endl;

if (!(lua_isnumber(L,-1)&&lua_isnumber(L,-2))

cout << "error" << endl;

cout << lua_tonumber(L,-1) <<endl;

cout << lua_tonumber(L,-2) <<endl;

lua_pop(L,2);

lua_close(L);

system("pause");

return 0;

}

test.lua

function hello()

print("Hello")

end

function add(x,y)

return x+y,x-y

end

luaL_loadfile 是加载一个chunk到栈顶,当 Lua 预编译一个 chunk 的时候, chunk 作为一个函数,整个函数体也就被预编译了,通过lua_gettop(L) lua_typename(L,lua_type(L,-1))返回值可证明,
Lua 执行了函数定义,这个函数本身就被实例化了,需要调用chunk中的函数(hello,add都在chunk中),先将chunk通过lua_pcall(L,0,0,0)实例化。所以如上代码多了一个函数调用实例化chunk。
上面可知Lua实现了一个虚拟栈,和C/C++交换数据都通过这个虚拟栈进行.lua_state就是这个栈的实现,c++与lua的定义类型不一样,通过显性调用C
API可以用来指明以哪种类型来解析数据。在内存的释放方面还不确定需要,后续查看lua的源码进行了解。。。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: