开发环境是Xcode5.1
1)使用Cocos Code IDE建立一个Lua工程,创建工程的时候记住选中add native code这个选项,这样会在工程目录下生成frameworks这个文件夹,里边是C++层的代码。
2)进入到frameworks的工程目录下,打开工程,我打开的是Xcode工程。
3)在工程中我们写自己的类,这个类就是你要导出给Lua层用的接口,实际的需求可能是你一直在c++层写代码,某一部分的功能需要在Lua层来实现,这个时候有一些类需要导出给Lua使用,下面写个简单的类用来测试。
//LuaBinding.h
#ifndef __LuaBinding__LuaBinding__
#define __LuaBinding__LuaBinding__
#include "cocos2d.h"
USING_NS_CC;
class LuaBinding : public Ref
{
public:
bool init()
{
return true;
};
CREATE_FUNC(LuaBinding);
int show(int);
};
#endif /* defined(__LuaBinding__LuaBinding__) */
//LuaBinding.cpp如果发现不是在Classes目录下,把这俩个文件复制到了Classes目录下一份(方便操作)。
#include "LuaBinding.h"
int LuaBinding::show(int temp)
{
log("success,number is %d", temp);
return temp;
}
4)然后编写.ini文件。在frameworks/cocos2d-x/tools/lua/目录下能看到genbindings.py脚本和一大堆.ini文件,这些就是bindings-generator的实际执行环境了。随便找一个内容比较少的.ini文件,复制一份,重新命名为Bind.ini。大部分内容都可以凑合不需要改,这里仅列出必须要改的重要部分:
frameworks/cocos2d-x/tools/tolua/Bind.ini
12345 | [Bind] prefix = Bind target_namespace = bb headers = %(cocosdir)s/../runtime-src/Classes/LuaBinding.h classes = Bind |
也即在Bind.ini中指定Bind.h文件的位置,指定要暴露出来的类,指定注册进Lua环境的模块名。中括号中的内容和你文件名相同,prefix同样和文件名相同,主要的是target_namespace,它的值代表的就是模块名,比如Cocos中的模块名cc,这里我使用的模块名是bb。headers代表的是头文件的路径,我引用的是Classes下的文件,classes代表的就是类名。
修改genbindings.py文件129行附近,将Bind.ini文件加进去:
frameworks/cocos2d-x/tools/tolua/genbindings.py
123 | cmd_args = { 'cocos2dx.ini' : ( 'cocos2d-x' , 'lua_cocos2dx_auto' ), \ 'Bind.ini' : ( 'Bind' , 'lua_binding_auto' ), \ } |
(其实这一步本来是可以省略的,只要让genbindings.py脚本自动搜寻当前目录下的所有ini文件就行了)
至此,生成桥接文件的准备工作就做好了,执行genbindings.py脚本:
1 | python genbindings.py |
在Mac系统上可能会遇到缺少yaml、Cheetah包的问题,安装这些Python包就可以,先sudo easy_install pip,把pip装好
然后 pip search yaml 再安装sudo pip install pyaml
pip search Cheetah 再安装sudo pip installCheetah
成功执行genbindings.py脚本后,会在frameworks/cocos2d-x/cocos/scripting/lua-bindings/auto/目录下看到新生成的文件lua_binding_auto.hpp/lua_binding_auto.cpp,在api文件夹下的LuaBinding.lua就是导出的LuaAPI。
每次执行genbindings.py脚本时间都挺长的,因为它要重新处理一遍所有的.ini文件,建议大胆修改脚本文件,灵活处理,让它每次只处理需要的.ini文件就可以了,比如像这个样子:
123 | cmd_args = {# 'cocos2dx.ini' : ( 'cocos2d-x' , 'lua_cocos2dx_auto' ), \ 'Bind.ini' : ( 'Bind' , 'lua_binding_auto' ), \ } |
5)下面我们就使用这个桥接类来将我们的类注册到Lua环境中。打开AppDelegate.cpp文件,包含一下桥接类lua_binding_auto.hpp,然后在applicationDidFinishLaunching函数中写如下的代码。
#include "AppDelegate.h"
#include "CCLuaEngine.h"
#include "SimpleAudioEngine.h"
#include "cocos2d.h"
#include "Runtime.h"
#include "ConfigParser.h"
#include "lua_binding_auto.hpp" //包含lua_binding_auto.hpp
using namespace CocosDenshion;
USING_NS_CC;
using namespace std;
.........
auto engine = LuaEngine::getInstance();
ScriptEngineManager::getInstance()->setScriptEngine(engine);
LuaStack* stack = engine->getLuaStack();
stack->setXXTEAKeyAndSign("2dxLua", strlen("2dxLua"), "XXTEA", strlen("XXTEA"));
//register custom function
//LuaStack* stack = engine->getLuaStack();
//register_custom_function(stack->getLuaState());
lua_getglobal(stack->getLuaState(), "_G");
register_all_binding(stack->getLuaState());
lua_settop(stack->getLuaState(), 0);
6)为了编译这个桥接类,我们需要将这个新生成的类加入到工程中,右键工程添加文件,添加进来桥接类。这个时候你会发现桥接类的.cpp文件处说找不到我们自己的类LuaBinding。所以还需要设置一下cocos2d_lua_bindings.xcodeproj子项目的User Header Search Paths的路径。
7) 经过这些步骤以后基本就算成功了,现在需要打开Cocos Code IDE的工程,重新build一下runtime,跑程序的时候我们使用这个最新的runtime,大家需要明确的一点是当我们改变c++层的代码的时候就需要重新build一下runtime,说白了就是重新编译一下c++的文件,让Lua脚本运行在一个新的环境下。
8) 打开工程的main.lua,在工程中使用导出来的接口,最终来验证一下是否成功。
collectgarbage("collect")bb 为命名空间,LuaBinding为类名,打开工程编译运行,成功
-- avoid memory leak
collectgarbage("setpause", 100)
collectgarbage("setstepmul", 5000)
local val = bb.LuaBinding:create():show(10)
print(val)