Lua与C++的集成

——一个最简单的Lua与C++的例子

很多人推荐脚本和引擎相结合,灵活又方便,但是以前没有这方面的经验,所以从头开始学习。

脚本方面选择了Lua,因为用得比较广,而且据说很简单!

开始之前要有心理准备,这东西,其实不简单!

或许Lua本身是简单的,或许Lua与C的集成也不难,但是如何在Lua中使用C++的类、对象和函数?特别是对以前没有使用过Lua的人来说,连语法和API都磕磕绊绊,要把Lua和C++集成在一起互相访问,其中需要打通的关节,很多……

第一个难点是:版本!

因为某些原因,我选择tolua++来生成Lua和C++之间的胶水文件。 Lua现在最新的版本是5.2.1,tolua++最新的版本是1.0.93,但是遗憾的是,这两个版本对不起来。1.0.93版的tolua++对应的是lua 5.1.4。我意识到这个问题,并就此请教google大神之前,已经在osx下奋战近2个小时了。

第二个难点是:编译!

理顺了版本只是第一步,接下来要把源代码编译成库文件。

一开始我是在osx下面,编译lua没有问题,但是tolua++失败了。tolua++需要使用scons来编译,scons需要python环境,这些都满足了之后,编译的时候还是提示很多错误,我没有细究,直接放弃了。

我也尝试像cocos2d-x那样把lua和tolua++放到工程中直接用xcode编译,但是也没有成功。于是不得不转战到Linux下面。

在Ubuntu下,用apt直接可以安装lua和tolua++。

tolua++安装好之后,你如果直接在shell里输入tolua++是找不到程序的。是用whereis tolua++命令可以发现,可执行文件的名字是:/usr/bin/tolua++5.1,为了方便,我建立了一个tolua++的链接。

第三个难点是:工具使用!

到这一步,已经不算难点了。在Linux下面,难度本身就减少了不少,但我还是遇到了一点点小问题。一开始,我只下载了tolua++,然后写了一个简单的头文件:

HelloWorld.h

class HelloWorld
{
public:
HelloWorld();

HelloWorld *GetInstance();
void PrintHello();
};

HelloWorld.cpp中是实现,随便写就可以了。

然后使用下面的命令,希望生成对应的cpp:
tolua++ -o hellulua.cpp HelloWorld.h
但是,貌似正确的结果中,却没有函数的内容。再在网上查了一些资料之后,我开始怀疑后缀名必须是.pkg才可以。测试了一下,结果正确了!

正确的pkg文件应该写成:

$#include "HelloWorld.h"

class HelloWorld
{
HelloWorld();
HelloWorld *GetInstance();
void PrintHello();
};

正确的命令,也不是使用.h文件,而是如下:
tolua++ -o hellulua.cpp HelloWorld.pkg

第四个难点是:集成!

或许是版本众多的原因,网上有很多相关的例子,但是都无法正确的运行。tolua++本身也带了一些测试,但是如果没有一定的基础,看起来也是非常困难的。总的来说,就是“不够简单”。经过多次失败,以及对lua文档的研习,再参考网上的例子,终于有了一个最简单的测试了。

#include <lua.hpp>
#include "HelloWorld.h"

int tolua_HelloWorld_open(lua_State* tolua_S);

int main(int argc, const char * argv[])
{
lua_State *L = luaL_newstate();//tolua_open()
luaopen_base(L);

tolua_HelloWorld_open(L);

int ret = luaL_dofile(L, "test.lua");

lua_close(L);
return 0;
}

这时候再回过去看tolua++的How to use toLua, 就可以很好的理解了。

用g++来编译:
g++ main.cpp HelloWorld.cpp hellolua.cpp -ltolua++5.1 -llua5.1 -I /usr/include/lua5.1
一开始我只下载了tolua++,所以编译的时候出现了一些reference没有找到的问题。再下载lua的开发库就OK了。

再写个test.lua文件:

hello = HelloWorld:new()
hello.PrintHello()

我在如何在Lua中使用C++类的构造函数上也花了很多时间。因为整个程序没有跑通,所以失败的时候,也不知道是语法不对,还是其他的问题。

然后运行编译出来的HelloWorld:
./a.out
就可以得到显示:
hello

至此,一个最简单的,在Lua脚本中使用C++对象的项目成功完成了。再回过来去看tolua++的文档,很多之前难懂的地方都清晰了。而且,有了这样一个最简单的项目,可以慢慢向里面添加更多Lua相关的东西,是深入学习Lua的一个好的起点。