cocos2d-x中C++回调Lua函数


前言

    最近做一个lua异步加载纹理的功能,在C++回调lua函数时,有时会发生崩溃的情况,原因可能是我直接使用了lua的api对堆栈操作而导致了数据出错,其实Cocos2dx已经封装好了相关的api,所以调用Cocos2dx的api就可以很方便的调用Lua函数。



在C++中如何表示Lua函数?


    通过查看CCScheduler中的scheduleScriptFunc方法可以看到在C++代码中是用unsigned int表示Lua函数的,其实int类型也可以。




示例代码


AsynResLoader.h

#ifndef  _ASYNRESLOADER_H_
#define _ASYNRESLOADER_H_

#include "cocos2d.h"

USING_NS_CC;

//供Lua调用的异步的资源加载器
class AsynResLoader: public CCObject
{
private:	
	int count;
	int total;
	//lua回调方法
	int mLuaCallback;
public:
	//创建一个异步资源加载器
	static AsynResLoader* create();
	//异步加载纹理
	void asynLoadTexture(CCArray* paths, int luaCallbck);
	//加载回调
	void callback(CCObject* pSender);
};

#endif

AsynResLoader.cpp

#include "AsynResLoader.h"
#include "CCLuaEngine.h"  

//创建一个异步资源加载器
AsynResLoader* AsynResLoader::create(){
	AsynResLoader* instance = new AsynResLoader;
	if (instance)
	{
		instance->autorelease();
		return instance;
	}
	return NULL;
}

//异步加载纹理
void AsynResLoader::asynLoadTexture(CCArray* paths, int luaCallback){	
	this->count = 0;
	this->total = paths->count();
	this->mLuaCallback = luaCallback;
	
	for(int idx = 0; idx <total; idx++)
	{
		const char* path = ((CCString*)paths->objectAtIndex(idx))->getCString();		
		CCLOG("asynLoadTexture PATH idx=%d : %s",idx,path);
		CCTextureCache::sharedTextureCache()->addImageAsync(path, this, callfuncO_selector(AsynResLoader::callback));
	}
}

//纹理加载回调方法
void AsynResLoader::callback(CCObject*){			
	this->count++;
	//当资源加载完成时,回调指定的lua函数
	if (this->count >= this->total)
	{
		CCLOG("asyn load res completed..");
		if (this->mLuaCallback)
		{			
			CCLuaStack* pStack = CCLuaEngine::defaultEngine()->getLuaStack();
			//第一个参数是函数的整数句柄,第二个参数是函数参数个数
			pStack->executeFunctionByHandler(this->mLuaCallback,0);
			pStack->clean();
			CCLOG("call lua function..");
		}
	}
}



绑定C++函数到Lua


点击查看tolua++工具的使用


当完成了自定义类的绑定后,如无意外应该会报错。。。


因为把Lua函数传递给C++代码时需要做一些预处理,做什么处理呢?我也不知道。。但可以参考Cocos2d-x的api,比如CCCallFuncN类是如何绑定到Lua的?


打开tolua++目录下的CCActoin.pkg文件,可以看到CCCallFuncN的create方法是用LUA_FUNCTION表示lua函数的。



于是,我把AsynResLoader类的pkg文件修改如下:

class AsynResLoader: public CCObject
{

	static AsynResLoader* create();

	void asynLoadTexture(CCArray* paths, LUA_FUNCTION luaCallbck);
};

然后,就成功啦。



在tolua++目录下有个build.bat(Mac下是build.sh)脚本,用于生成LuaCocos2d.cpp,该脚本是这样的:

tolua++ -L basic.lua -o "../../scripting/lua/cocos2dx_support/LuaCocos2d.cpp" Cocos2d.pkg

其中有一个参数是basic.lua,在tolua++目录下也有这个文件,对Lua函数传递到C++中的预处理就是在这个文件中实现的。



posted on 2014-09-27 15:40  linchaolong  阅读(734)  评论(0编辑  收藏  举报

导航