tolua++使用SCons进行编译,我们也可以使用自己喜欢的IDE新建一个控制台(Console)工程,然后将源码下bin目录中所有文件加入到工程中,直接编译即可;同样地,新建一个静态库(StaticLibrary)工程,将源码下lib目录中所有文件加入进入,编译即可。当然了,这些工程是需要lua库支持的,目前tolua++最新版本是1.0.93,支持lua5.1.x。
经过上面的步骤,在Windows系统上的话,你会得到tolua++.exe和tolua.lib,前者是一个辅助工具,用来将.pkg文件(下面将会讲到)转换成源代码,而后者则是我们需要在自己工程中加入的函数库。
下面开始正式使用tolua++。
一开始,我们并不需要特别注意,按照自己的需要来撰写完完全全的C++代码,假设我们有一个基于控制台的项目,名为mytest,设置好项目属性,包含必要的库(包括lua和tolua++),添加如下代码:// file: UsingIt.h
#include<iostream>
classmy_class
{
public:
void greet()
{
std::cout << “Hello World!” << std::endl;
}
};
好,下面撰写我们的.pkg文件:// file: mylib.pkg
$pfile“UsingIt.h”
classmy_class
{
my_class();
~my_class();
void greet();
};
还记得我们的tolua++.exe吗?是时候派上用场了: > tolua++ -n mylib -o mylib.cpp mylib.pkg
这条命令的意思是:使用tolua++程序,从mylib.pkg生成源代码并输出到mylib.cpp,而-n参数则是用来指定包名称的(lua 中package name)。你会得到mylib.cpp,文件,其中包含一个很重要的函数:int tolua_<package name>_open(lua_State*)。"packagename”就是用-n指定,这里就是int tolua_mylib_open(lua_State*),它的功能就是将你在.pkg文件中所撰写的类、函数接口等注册给lua,这个函数是需要你自己调用的。
回到我们的mytest项目,将上面得到的mylib.cpp文件加入到项目中,添加一个新文件Main.cpp://file: Main.cpp
#include<iostream>
#include<tolua++.h>
extern“C” {
#include"lua.h"
#include"lauxlib.h"
}
#include“UsingIt.h”
intmain()
{
lua_State* L = lua_open();
luaL_openlibs(L);
tolua_mylib_open(L); // 打开mylib
luaL_dofile(L, “mytest.lua”); // 执行脚本文件
lua_close(L);
return 0;
}
mytest.lua脚本文件内容:
localmy = my_class()
my:greet()
好了,编译并运行你的mytest程序吧,你将看到 Hello World! 出现在你的屏幕上!
就说到这里了,更深入的使用请参考tolua++的文档,有一点需要注意的是,tolua++并不支持导出虚函数类供lua代码派生实现。但是这一点并非不可克服,后面我们会讲到该如何解决。
使用tolua++实现虚函数
前面我撰写了一篇《tolua++快速入门》,介绍了如何迈入tolua++的使用大门。这次,我们来谈点高级的东西:使用虚函数。
本文来源于实际项目经验,但技术要点则是基于一篇文章:《Implementing VirtualMethods With Toluapp》。
具体的使用方法,你可以详细阅读该文,请注意该文后面的一段:
Someversions of tolua++ (like 1.0.92) have problems with the'default_private_access' flag. If the methods on your virtual class are notbeing exported, try setting the flag to false. You'll have to add a private:label to the class declarations that have private stuff by default at thebeginning.
该说明适用于tolua++最新版本1.0.93,所以,你需要在实际使用中做相应调整。
另外一个需要注意的则是名字空间,如果你在.pkg中使用了名字空间:
namespacemylib
{
class A {…};
class B : public A {…};
}
在导出类有虚函数的情况下导出的代码是无法通过编译的,因为在额外导出代码函数中会加入名字空间限定,这个可以通过手工移除该限定来解决,但每次导出都这样你肯定会觉得烦!我的建议是将namespacemylib替换为module mylib,然后在导出源码中加入using namespace mylib;。聪明的你甚至可以在.pkg中加入一个额外的头文件来避免每次导出都需要增加这行代码,完美!