这个系列我们主要学习Cocos2d-x Lua,总结Lua开发过程中所涉及的知识点,以及在开发过程中如何使用Cocos Code IDE。这一篇讲解HTTP工具类封装

实现

该工具类对Cocos2d-x中的HttpClient进行了封装,使可以在Lua中实现http异步请求。

LuaHttpClient.h

#ifndef __LUAHTTPCLIENT_H__
#define __LUAHTTPCLIENT_H__

#include "cocos2d.h"
USING_NS_CC;

#include "cocos-ext.h"
USING_NS_CC_EXT;

// 参数封装类
class LuaParams{
public:

	static LuaParams* create(){
		LuaParams* params = new LuaParams(); // 参数在回调后释放
		params->setTypeName("nil");
		return params;
	};
	static LuaParams* create(const char* url,
											int func,
											const char* data,
											CCObject* obj ,
											const char* typeName = "nil"){
			LuaParams* params = new LuaParams();
			params->setData(data);
			params->setUrl(url);
			params->setFunc(func);
			params->setCCObjct(obj);
			params->setTypeName(typeName);			
			return params;
	};

	void setFunc(int func_){
		func = func_;
	};
	int getFunc(){
		return func;
	};

	void setCCObjct(CCObject* obj_){
		obj = obj_;
	};
	CCObject* getCCObjct(){
		return obj;
	};

	void setTypeName(const char* typeName_){
		typeName = typeName_;
	};
	const char* getTypeName(){
		return typeName;
	};

	void setUrl(const char* url_){
		url = url_;
	};
	const char* getUrl(){
		return url;
	};

	void setData(const char* data_){
		data = data_;
	};
	const char* getData(){
		return data;
	};
private:
	/** POST请求数据 **/
	const char* data;	
	/** 请求地址 **/
	const char* url;
	/** Lua回调方法 **/
	int func;
	/** 用户数据 **/
	CCObject* obj;
	/** 用户数据类型名称 **/
	const char* typeName;
};

// Lua异步http请求工具类
class LuaHttpClient:public CCObject{
public:
	// 单例
	static LuaHttpClient* getInstance();
	// 异步Get请求
	void asynGet(LuaParams* params);
	// 异步Post请求
	void asynPost(LuaParams* params);
	// 回调函数
	void callback(CCHttpClient *sender, CCHttpResponse *response);  
};

#endif

LuaHttpClient.cpp

#include "LuaHttpClient.h"
#include "../cocos2dx_support/CCLuaEngine.h"

static LuaHttpClient* s_instance = NULL;

LuaHttpClient* LuaHttpClient::getInstance(){
	if (s_instance == NULL)
	{
		s_instance = new LuaHttpClient();
		s_instance->autorelease();
	}
	return s_instance;
}

void LuaHttpClient::asynGet(LuaParams* params){
	CCHttpRequest* request = new CCHttpRequest();
	request->setUrl(params->getUrl());
	request->setRequestType(CCHttpRequest::kHttpGet);
	request->setResponseCallback(this, httpresponse_selector(LuaHttpClient::callback));				
	request->setUserData((void*)params);
	CCHttpClient::getInstance()->send(request);	

	if (params->getTypeName() != "nil")
	{	
		params->getCCObjct()->retain(); //引用计数+1
	}
}

void LuaHttpClient::asynPost(LuaParams* params){
	CCHttpRequest* request = new CCHttpRequest();
	request->setUrl(params->getUrl());
	request->setRequestType(CCHttpRequest::kHttpPost);
	request->setResponseCallback(this, httpresponse_selector(LuaHttpClient::callback));	
	request->setUserData((void*)params);
	// write the post data
	request->setRequestData(params->getData(), strlen(params->getData())); 	
	CCHttpClient::getInstance()->send(request);
	request->release();

	if (params->getTypeName() != "nil")
	{	
		params->getCCObjct()->retain(); //引用计数+1
	}
}

void LuaHttpClient::callback(CCHttpClient *sender, CCHttpResponse *response){

	if (!response)
	{
		return;
	}

	int statusCode = response->getResponseCode();
	char statusString[64] = {};
	sprintf(statusString, "HTTP Status Code: %d, tag = %s", statusCode, response->getHttpRequest()->getTag());	
	CCLog("response code: %d", statusCode);

	// 回调Lua函数
	LuaParams* params = (LuaParams*)response->getHttpRequest()->getUserData();

	if (!response->isSucceed()) 
	{
		CCLog("response failed");
		CCLog("error buffer: %s", response->getErrorBuffer());
		// 释放内存
		if (params->getTypeName() != "nil")
		{	
			params->getCCObjct()->release();	//引用计数-1
		}
		delete params;
		return;
	}

	// dump data
	std::vector<char> *buffer = response->getResponseData();
	std::string data (buffer->begin(),buffer->end());  

	CCLOG("request success");

	CCLuaStack* pStack = CCLuaEngine::defaultEngine()->getLuaStack();
	pStack->pushString(data.c_str());	//把服务器回应的数据添加到函数参数1

	//if (params->getCCObjct() && params->getTypeName()) //这个判断不知道为什么有一定随机性
	if (params->getTypeName() != "nil")
	{
		// 如果传递了CCObject,把它作为第二个参数
		pStack->pushCCObject(params->getCCObjct(),params->getTypeName());
		pStack->executeFunctionByHandler(params->getFunc(),2);
		pStack->clean();			
		params->getCCObjct()->release();	//引用计数-1
	}else{
		//第一个参数是函数的整数句柄,第二个参数是函数参数个数
		pStack->executeFunctionByHandler(params->getFunc(),1);
		pStack->clean();			
	}	
	delete params;
}


绑定到Lua

工程下载:http://upyun.cocimg.com/cocos/Cocos2d-x_LuaHttpClient-master.zip

该工程使用Cocos2d-x-2.2.6和vs2012,把工程放到引擎projects目录下即可:

1. 把“绑定自定义类到lua”目录下的ext文件夹放到cocos2d-x-2.2.6\scripting\lua目录下

2. 其它文件放到cocos2d-x-2.2.6\tools\tolua++目录下,点击build_ext.bat生成绑定文件

3. 把LuaExt.h和LuaExt.cpp放到cocos2d-x-2.2.6\scripting\lua\cocos2dx_support下

4. 修改CCLuaStack.cpp,在init方法下调用tolua_Ext_open方法注册自定义C++类

#include "LuaExt.h" //包含头文件
m_state = lua_open();
luaL_openlibs(m_state);
tolua_Cocos2d_open(m_state);
tolua_Ext_open(m_state);  //注册自定义类
toluafix_open(m_state);

5.在项目中引入文件

20141223091238812.jpg

点击查看:绑定C++自定义类到Lua


调用示例

在Lua中调用的示例代码

-- 在主线程中创建一个CCLayer
local layer2 = CCLayerColor:create(ccc4(200,0,0,200))
    
-- 回调函数(参数1:服务返回的数据,参数2:用户数据(CCObject))
local callback = function(responseData, userdata)
    cclog("lua response data : %s",responseData)
    -- 替换场景
    local scene = CCScene:create()
    scene:addChild(userdata) -- 添加主线程中创建的CCLayer到场景
    CCDirector:sharedDirector():replaceScene(scene)
end
    
-- 1.异步http get请求并,传递一个CCObject    
   local params = LuaParams:create("http://www.baidu.com",callback,"",layer2,"CCLayer")
-- 2.异步http get请求   
--   local params = LuaParams:create()
--   params:setUrl("http://www.baidu.com")
--   params:setFunc(callback)
pClient:getInstance():asynGet(params) --发起请求


<