网上关于tolua++的资料实在是太少,而且大多是转载,大牛们很少分享,目前项目要用到lua总结一下自己的学习经验,对于lua新手还是值得借鉴,
如果是大牛请转频道。
本人Cocos2dx的版本是2.2.2,项目正在使用cocos2dx的lua绑定,绑定的方式是tolua++。对大规模使用lua代码信心不是很足,花了一些时间阅读tolua++的代码,希望对绑定实现的了解,有助于项目对lua代码的把控。
tolua++在tools文件夹中,有兴趣的小伙伴可以去看看。
tolua++ 是一个将 C/C++ 的函数和对象导出给 Lua 脚本使用的工具。
使用这个工具的基本步骤:
- 将要导出的 C/C++ 函数和对象定义写入 .pkg 文件;
- 运行 tolua++ 工具,将 .pkg 文件编译为目标 .cpp 文件;
- 将目标 .cpp 文件加入项目,在启用 Lua 虚拟机后调用目标文件中的 open() 函数注册导出的内容。
网上讲解的大多是使用如下指令:
tolua++ -L basic.lua -o MyLuaSNSprite.cpp MyLuaSNSprite.pkg
把自定义类的文件导入到LuaCocos2d.cpp里面,然后在LuaCocos.h中添加相应的自定义类的头文件即可使用,但对于一个项目来说全部的自定义类放在LuaCocos2d.cpp中过于臃肿,也不便管理,本人在项目中专门做了一个自定义类和那些使用c++实现的底层功能的供Lua调用的库,把自定义类生成相应的cpp文件,导入项目中使用,这样便于管理,废话不多说了,上图上例子上代码:
首先使用c++实现一些功能准备调用,需要的文件:头文件,cpp源文件,pkg文件
附上代码如下:
SNSprite.h
#ifndef __LuaDemo__SNSprite__
#define __LuaDemo__SNSprite__
#include "cocos2d.h"
USING_NS_CC;
class SNSprite : public CCSprite{
public:
static SNSprite* create(const char* name);
private:
void initData();
};
#endif /* defined(__LuaDemo__SNSprite__) */
SNSprite.cpp
#include "SNSprite.h"
SNSprite* SNSprite::create(const char* name){
SNSprite* sprite = new SNSprite();
if(sprite && sprite->initWithFile(name)){
sprite->initData();
sprite->autorelease();
return sprite;
}
CC_SAFE_DELETE(sprite);
return NULL;
}
void SNSprite::initData(){
CCActionInterval* action = CCSequence::createWithTwoActions(CCMoveTo::create(1.0, ccp(300,300)),
CCMoveTo::create(1.0, ccp(100,100)) );
this->runAction(CCRepeatForever::create(action));
}
实现的都是很简单的功能
SNSprite.pkg
class SNSprite : public CCSprite{
static SNSprite* create(const char* name);
};
pkg文件不会写的小伙伴,可以去看看tolua++目录下的README文件,里面很详细
为了执行如下指令,我们还需要一个pkg文件:
MyLuaSNSprite.pkg
$pfile "SNSprite.pkg"
然后把pkg文件和tolua++.exe放在同一个目录执行如下指令:
tolua++ -o MyLuaSNSprite.cpp MyLuaSNSprite.pkg(这是tolua++最原生态的用法)
如果在cocos2dx中使用,由于cocos2dx的内存管理机制,推荐使用一下命令
tolua++ -L basic.lua -o MyLuaSNSprite.cpp MyLuaSNSprite.pkg
如果顺利的话,就可以得到一个MyLuaSNSprite.cpp的文件
打开MyLuaSNSprite.cpp文件,可以看到有一个导出函数
/* Exported function */
TOLUA_API int tolua_MyLuaSNSprite_open (lua_State* tolua_S);
然后把SNSprite.h,SNSprite.cpp,MyLuaSNSprite.cpp加入工程中,在使用MyLuaSNSprite.cpp之前我们需要做一下加工,拆分MyLuaSNSprite.cpp成MyLuaSNSprite.cpp和MyLuaSNSprite.h两个文件, 如何拆分,把头文件的包含和函数的声明等等之类的拷到头文件。
把MyLuaSNSprite.cpp里面的如下内容剪切到新建的MyLuaSNSprite.h中,部分内容需要去LuaCocos2d.h里面去拷贝,最终拆分好的MyLuaSNSprite.h和MyLuaSNSprite.cpp如下:
MyLuaSNSprite.h
#ifndef __MYLUASNSPRITE_H_
#define __MYLUASNSPRITE_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "tolua++.h"
#ifdef __cplusplus
}
#endif
#include "cocos2d.h"
#include "SNSprite.h"
#include "string.h"
/* Exported function */
TOLUA_API int tolua_MyLuaSNSprite_open (lua_State* tolua_S);
#endif // __MYLUASNSPRITE_H_
再在MyLuaSNSprite.cpp中加入MyLuaSNSprite.h头文件
被处理后的MyLuaSNSprite.cpp前面的内容如下:
#include "MyLuaSNSprite.h"
#ifndef __cplusplus
#include "stdlib.h"
#endif
/* function to register type */
static void tolua_reg_types (lua_State* tolua_S)
{
tolua_usertype(tolua_S,"SNSprite");
tolua_usertype(tolua_S,"CCSprite");
}
........//后面内容省略和之前的MyLuaSNSprite.cpp一样
然后再hello.lua里面添加如下代码:
--createSunnyLayer
local function createSunnyLayer()
local layerSunny = CCLayer:create()
local labTips = CCLabelTTF:create("这个icon图标就是使用的自定义类", "Arial", 18)
labTips:setPosition(ccp(240,280))
layerSunny:addChild(labTips)
local sp = SNSprite:create("dog.png")
sp:setPosition(ccp(100,100))
layerSunny:addChild(sp)
return layerSunny
end
-- run
local sceneGame = CCScene:create()
--sceneGame:addChild(createLayerFarm())
--sceneGame:addChild(createLayerMenu())
sceneGame:addChild(createSunnyLayer())
CCDirector:sharedDirector():runWithScene(sceneGame)
最后保存所有的文件,在AppDelegate.cpp中添加如下代码:
#include "MyLuaSNSprite.h"
tolua_MyLuaSNSprite_open(tolua_s);
然后启动调试工程,ok一切大工告成
lua调用c++自定义类就是这么简单,哇哈哈