tolua++ 是用来把 C++代码 生成 在Lua中使用的接口的工具,编译步骤比较繁琐。
使用tolua有以下步骤:
1. 工程建立:
1).下载http://www.lua.org/versions.html#5.3
2).下载tolua-5.2.4
Tulua官网http://webserver2.tecgraf.puc-rio.br/~celes/tolua/,更新到tolua-5.2.4,支持lua5.2.4。官网只提供了tolua的源代码,没有提供任何程序。
下载代码解压后,在src目录下有三个目录,如下:
Bin目录中包含了生成tolua++.exe转换程序的代码,我以使用VS2015编译,文章最后有下载地址。
Lib目录包含了程序使用tolua时需要包含的库的代码,因为代码比较少,我一般直接将lib文件夹中的代码直接包含到程序中。
Tests目录包含了tolua的一些例子,这些例子我以全部使用VS2015进行了编译,文章最后有下载地址。
3) VS2017工程建立
a. lua5.3.5: 在项目中去除掉lua.c和luac.c文件.
b. tolua在Bin目录下有两个.c文件,tolua.c、toluabind.c,将这两个文件加入到项目中,另外项目中还须要lua5.2.4代码和Lib目录下的代码.。如下:
1. tolua++.exe 生成
2. tolua++.lib
修改完成后再点击编译,终于生成“tolua++.exe”文件了:
编写pkg文件
pkg文件语法,这里不讲解,具体情况tolua官网:http://webserver2.tecgraf.puc-rio.br/~celes/tolua/tolua-3.2.html。语法规则不多,与C++非常接近,很容易看懂。
导出源文件
上面讲了使用 tolua 的三部曲,下面使用实际例子讲解一下。首先,正常编写 c++ 代码,这里我们创建一个类
原始头文件
//mylib.h
class Test
{
public:
Test(int a, int b);
~Test();
void sayHello();
int add();
int getA();
private:
int a;
int b;
};
原始源文件
//mylib.cpp
#include "mylib.h"
#include
Test::Test(int a, int b)
{
this->a = a;
this->b = b;
}
Test::~Test()
{
}
void Test::sayHello()
{
std::cout << "hello world" << std::endl;
}
int Test::add()
{
return this->a + this->b;
}
int Test::getA()
{
return this->a;
}
package 文件
$#include "mylib.h"
class Test
{
Test(int, int);
~Test();
void sayHello();
int add();
int getA();
};
可以看到 package 文件和 c++ 头文件基本一致,要注意的是要在文件头引入头文件,然后把 public 关键字去掉。所有公有的函数或数据都可以导出,如果不想导出某个函数,则在 package 文件中不要定义就可以了。
然后打开命令行,输入下面的命令
tolua -n mylib -o tolua.cpp mylib.pkg
导出的文件名可以任意命名,但因为我们已经有一个原始的源文件 mylib.cpp 了,所以这里不能将导出的源文件命名为 mylib.cpp,否则后面使用的时候就会有问题,这里我命名为 tolua.cpp。还有一个要注意的就是必须把 mylib.h 跟 mylib.pkg 放在一起,因为 package 文件需要用到头文件(第一行就已经引入头文件了)
现在我们有了 mylib.h、mylib.cpp 和 tolua.cpp 这三个文件,接下来就可以在项目中使用了
在 c++ 程序中使用 tolua
新建一个 c++ 控制台程序,因为要使用到 lua 和 tolua,所以要把相应的头文件和库文件包含进来,头文件有 lua.h、lualib.h、lauxlib.h、lua.hpp、luaconf.h 和 tolua.h,库文件则有 lua.lib 和 tolua.lib。
首先,我们先来测试一下 lua 环境,新建一个 main.cpp 文件,输入下面代码
//main.cpp
#include
extern "C"
{
#include "lualib.h"
#include "lauxlib.h"
}
using namespace std;
int main()
{
int tolua_mylib_open(lua_State*);
lua_State* state = luaL_newstate();
luaL_openlibs(state);
if (luaL_dostring(state, "print([[hello world]])") != 0)
{
cout << "excute lua file failed!" << endl;
}
lua_close(state);
system("pause");
return 0;
}
如果正确打印出 “hello world”,则说明 lua 环境没有问题,否则就检查一下头文件和库文件是否正确引入了
接下来把 mylib.h、mylib.cpp 和 tolua.cpp 这三个文件添加到项目中,我们先来分析下 tolua.cpp 这个文件的内容
static int tolua_collect_Test (lua_State* tolua_S){}
static void tolua_reg_types (lua_State* tolua_S){}
//对应构造函数
static int tolua_mylib_Test_new00(lua_State* tolua_S){}
//对应析构函数
static int tolua_mylib_Test_delete00(lua_State* tolua_S){}
//sayHello
static int tolua_mylib_Test_sayHello00(lua_State* tolua_S){}
//add
static int tolua_mylib_Test_add00(lua_State* tolua_S){}
//getA
static int tolua_mylib_Test_getA00(lua_State* tolua_S){}
LUALIB_API int luaopen_mylib (lua_State* tolua_S){}
TOLUA_API int tolua_mylib_open (lua_State* tolua_S){}
这里只列出主要的几个函数,可以看到 tolua 在导出 c++ 源码的时候为每个函数都生成一个对应的静态函数;除此之外,还有几个重要的函数,tolua_collect_Test 用于垃圾回收,tolua_reg_types 用于注册类名,toluaopen_mylib 用于打开库函数,tolua_mylib_open 用于打开 tolua,这是我们唯一关心的函数,在使用 tolua 之前必须先调用这个函数,这样所有导出的 c++ 函数就可以在 lua 中使用了
接下来开始测试在 lua 中访问 c++ 函数,新建一个 test.lua 文件,输入下面代码
local test = Test:new(1, 2)
test:sayHello()
print("a = " .. test:getA())
print("a + b = " .. test:add())
然后修改 main.cpp 文件
#include
extern "C"
{
#include "lualib.h"
#include "lauxlib.h"
}
#include "mylib.h"
using namespace std;
int main()
{
int tolua_mylib_open(lua_State*);
lua_State* state = luaL_newstate();
luaL_openlibs(state);
tolua_mylib_open(state);
if (luaL_dofile(state, "scripts/test.lua") != 0)
{
cout << "excute lua file failed!" << endl;
lua_close(state);
return 1;
}
lua_close(state);
system("pause");
return 0;
}
首先,要引入 mylib.h 头文件,然后调用 tolua_mylib_open(state); 打开 tolua,这个函数在 tolua.cpp 文件中定义和实现,main.cpp 并不知道这个函数,所以要在使用前手动定义一下 int tolua_mylib_open(lua_State*);,之后就可以执行 test.lua 文件了
如果没错误,将会看到下面的执行结果
如果没错误,将会看到下面的执行结果