lua提供了很多c api是的lua与c可以非常方便的交互然而实际运用的交互是需要使用c++ java objc等语言来与lua交互实现功能,
在cocos 将c++类注册到lua 主要关心将类对象实例化函数注册给lua以及实例对象的函数注册到lua, 将类对象注册为usertype,将函数注册在类module下
DEMO CODE
// 以c编译模式引入tolua++
#ifdef __cplusplus
extern "C" {
#endif
#include "tolua++.h"
#ifdef __cplusplus
}
#endif
TOLUA_API int register_test_binding(lua_State* tolua_S);
// 定义好的c++类以及他的public函数注册给lua
class DrawNode3D: public Node
{
public:
static DrawNode3D* create();
void drawLine(const Vec3 &from, const Vec3 &to, const Color4F &color);
void drawCube(Vec3* vertices, const Color4F &color);
const BlendFunc& getBlendFunc() const;
void setBlendFunc(const BlendFunc &blendFunc);
void onDraw(const Mat4 &transform, uint32_t flags);
};
int lua_cocos2dx_DrawNode3D_getBlendFunc(lua_State* L)
{
int argc = 0;
cocos2d::DrawNode3D* cobj = nullptr;
bool ok = true;
#if COCOS2D_DEBUG >= 1
tolua_Error tolua_err;
#endif
#if COCOS2D_DEBUG >= 1
// 校验 drawNode 的usertype是否在栈底
if (!tolua_isusertype(L,1,"cc.DrawNode3D",0,&tolua_err)) goto tolua_lerror;
#endif
// 将栈底的userType 转化为 c++的drawNode对象指针
cobj = (cocos2d::DrawNode3D*)tolua_tousertype(L,1,0);
#if COCOS2D_DEBUG >= 1
if (!cobj)
{
tolua_error(L,"invalid 'cobj' in function 'lua_cocos2dx_DrawNode3D_getBlendFunc'", nullptr);
return 0;
}
#endif
// 获取栈的长度也就是参数长度
argc = lua_gettop(L)-1;
if (argc == 0)
{
if(!ok)
return 0;
// 执行c++函数
const cocos2d::BlendFunc& ret = cobj->getBlendFunc();
// 压入栈道lua
blendfunc_to_luaval(L, ret);
return 1;
}
CCLOG("%s has wrong number of arguments: %d, was expecting %d \n", "cc.DrawNode3D:getBlendFunc",argc, 0);
return 0;
#if COCOS2D_DEBUG >= 1
tolua_lerror:
tolua_error(L,"#ferror in function 'lua_cocos2dx_DrawNode3D_getBlendFunc'.",&tolua_err);
#endif
return 0;
}
int lua_cocos2dx_DrawNode3D_create(lua_State* L)
{
int argc = 0;
bool ok = true;
#if COCOS2D_DEBUG >= 1
tolua_Error tolua_err;
#endif
#if COCOS2D_DEBUG >= 1
// 检查栈底类型
if (!tolua_isusertable(L,1,"cc.DrawNode3D",0,&tolua_err)) goto tolua_lerror;
#endif
argc = lua_gettop(L) - 1;
//检查参数数量
if (argc == 0)
{
if(!ok)
return 0;
//创建c++对象
cocos2d::DrawNode3D* ret = cocos2d::DrawNode3D::create();
//将对象压栈给lua
object_to_luaval(L, "cc.DrawNode3D",(cocos2d::DrawNode3D*)ret);
return 1;
}
CCLOG("%s has wrong number of arguments: %d, was expecting %d\n ", "cc.DrawNode3D:create",argc, 0);
return 0;
#if COCOS2D_DEBUG >= 1
tolua_lerror:
tolua_error(L,"#ferror in function 'lua_cocos2dx_DrawNode3D_create'.",&tolua_err);
#endif
return 0;
}
int lua_cocos2dx_DrawNode3D_setBlendFunc(lua_State* L)
{
int argc = 0;
cocos2d::DrawNode3D* cobj = nullptr;
bool ok = true;
#if COCOS2D_DEBUG >= 1
tolua_Error tolua_err;
#endif
#if COCOS2D_DEBUG >= 1
if (!tolua_isusertype(L,1,"cc.DrawNode3D",0,&tolua_err)) goto tolua_lerror;
#endif
//获取到lua中的c++对象指针
cobj = (cocos2d::DrawNode3D*)tolua_tousertype(L,1,0);
#if COCOS2D_DEBUG >= 1
if (!cobj)
{
// 如果对象被释放了会向lua报错
tolua_error(L,"invalid 'cobj' in function 'lua_cocos2dx_DrawNode3D_setBlendFunc'", nullptr);
return 0;
}
#endif
// 检测参数数量
argc = lua_gettop(L)-1;
if (argc == 1)
{
cocos2d::BlendFunc arg0;
ok &= luaval_to_blendfunc(L, 2, &arg0, "cc.Sprite3D:setBlendFunc");
if(!ok)
{
tolua_error(L,"invalid arguments in function 'lua_cocos2dx_DrawNode3D_setBlendFunc'", nullptr);
return 0;
}
// 执行对象函数
cobj->setBlendFunc(arg0);
return 0;
}
CCLOG("%s has wrong number of arguments: %d, was expecting %d \n", "cc.DrawNode3D:setBlendFunc",argc, 1);
return 0;
#if COCOS2D_DEBUG >= 1
tolua_lerror:
tolua_error(L,"#ferror in function 'lua_cocos2dx_DrawNode3D_setBlendFunc'.",&tolua_err);
#endif
return 0;
}
int lua_register_cocos2dx_DrawNode3D(lua_State* L)
{
// 创建cc.DrawNode3D lua userType
tolua_usertype(L,"cc.DrawNode3D");
// 注册为cc在lua的类
tolua_cclass(L,"DrawNode3D","cc.DrawNode3D","cc.Node",nullptr);
// 开启drawNode module
tolua_beginmodule(L,"DrawNode3D");
//依次想drawNode 添加成员函数
tolua_function(L,"getBlendFunc",lua_cocos2dx_DrawNode3D_getBlendFunc);
tolua_function(L,"setBlendFunc",lua_cocos2dx_DrawNode3D_setBlendFunc01);
tolua_function(L,"drawLine",lua_cocos2dx_DrawNode3D_drawLine);
tolua_function(L,"clear",lua_cocos2dx_DrawNode3D_clear);
tolua_function(L,"drawCube",lua_cocos2dx_DrawNode3D_drawCube);
tolua_function(L,"create", lua_cocos2dx_DrawNode3D_create);
// 关闭drawNode module
tolua_endmodule(L);
std::string typeName = typeid(cocos2d::DrawNode3D).name();
g_luaType[typeName] = "cc.DrawNode3D";
g_typeCast["DrawNode3D"] = "cc.DrawNode3D";
return 1;
}
int register_test_binding(lua_State* L)
{
//开lua栈
tolua_open(L);
//开启cc module 如果存在则不会创建拿旧的
tolua_module(L, "cc", 0);
// 开始module下的成员添加
tolua_beginmodule(L, "cc");
// 注册drawNode
lua_register_cocos2dx_DrawNode3D(L);
// module成员添加
tolua_endmodule(L);
return 0;
}