cocos2d-x lua 中使用protobuf并对http进行处理
cocos2d-x lua 中使用protobuf并对http进行处理
本文介绍 cocos2d-x lua 中使用http 和 基于cocos2d-x 对lua http的封装(部分ok)
本博客链接
http://blog.csdn.net/vpingchangxin/article/details/24458051
protobuf Google的一个非常好用的数据传输的封装 说实话Google的东西确实比較好用 所以我们前后端数据交换就用他了 只是Google没有对lua进行支持 还好社区有开源的大侠们贡献 找了全部关于lua protobuf 我仅仅找到 云风的 pbc 改动相关cocos2d-x中的类能够正常使用。protoc-gen-lua 我在使用的时候 总是报截断数据 在改动后cocs2d-x中的类之后没有对protoc-gen-lua 进行測试是否是这个问题导致
1)集成 云风 云大侠的(博客)lua-pbc 标准c写的protobuf 详细看pbc的帮助非常轻松集成
2) 生成pb文件(我自己写了个mac中批处理生成全部.proto文件为.pb文件)把pb 和proto文件都增加到项目资源中
#!/bin/sh
#pb = "pb"
for i in *.proto
do
#echo $i
#echo ${i%.*}".pb"
#echo ${i%.*}
#pbn = $i | cut -d.
pbname=${i%.*}".pb"
#echo $pbn
#echo $pbname
protoc --descriptor_set_out $pbname $i
done
echo "finish"
也能够用命令行手动生成
protoc --descriptor_set_out aaa.pb aaa.proto
3)本步骤能够忽略了,能够直接用io进行读取(Android是路径问题请看本文最以下解释)在lua中使用例如以下代码(我用的是cocos2d-x中绑定的CCFileUtils中的获取文件的方式,只是要手动用tolua++进行绑定到lua,能够參考我上个文章中的绑定方式,云大侠中的
用lua io形式获取在相关了解中不能跨平台全部就用这个了)
local protobuf = require "protobuf"
local buffer = CCFileUtils:sharedFileUtils():getFileData("entity/p_result.pb","r",0)
-- print(buffer)
protobuf.register(buffer)
4)本步骤能够忽略了。能够直接用io进行读取(Android是路径问题请看本文最以下解释) 上一步完毕后我们要对提到的CCFileUtils.cpp中的类进行改动 假设不改动读文件pb文件会时好时坏 原因是 读文件的时候结束总是加入多余字节我也不清楚这个问题 进行改动cocos2d-x中CCFileUtils.cpp的以下方法中的读取数据后处理并在tolua++
中加入以下方法绑定到lua层
改动CCFileUtils.cp getFileData(const
char* pszFileName, const char* pszMode,unsignedlong * pSize)方法(在最后加入\0。保证字节不多余)例如以下代码
unsigned char* CCFileUtils::getFileData(const char* pszFileName, const char* pszMode, unsigned long * pSize)
{
unsigned char * pBuffer = NULL;
CCAssert(pszFileName != NULL && pSize != NULL && pszMode != NULL, "Invalid parameters.");
*pSize = 0;
do
{
// read the file from hardware
std::string fullPath = fullPathForFilename(pszFileName);
FILE *fp = fopen(fullPath.c_str(), pszMode);
CC_BREAK_IF(!fp); fseek(fp,0,SEEK_END);
*pSize = ftell(fp); fseek(fp,0,SEEK_SET);
pBuffer = new unsigned char[*pSize];
*pSize = fread(pBuffer,sizeof(unsigned char), *pSize,fp);
fclose(fp); } while (0); if (*pSize >0 && pBuffer[*pSize] != '\0')
pBuffer[*pSize] = '\0'; if (! pBuffer)
{
std::string msg = "Get data from file(";
msg.append(pszFileName).append(") failed!"); CCLOG("%s", msg.c_str());
}
return pBuffer;
}
5)经过上一步骤lua层基本搞定能够创建本地的数据并encode成数据传输到server端了 例如以下代码
local major = {
majorId = "795f94a9-3466-41b4-bf16-043ba8081fab"
}
local buffer = protobuf.encode("com.sj.web.proto.Major", major)
6)我们client传输数据到server端 server端会返回数据给我们 相同我们接收的数据肯定也是protobuf数据了 用 protobuf.decode进行解数据
local t = protobuf.decode("com.sj.web.proto.Result", request:getResponseString())--tolua.cast(event.dataCString))--tolua.cast(event.dataCString,"CCString"):getCString())
cclog(t) print(t.major.gender)
print(t.major.majorId)
print(t.user.username)
7)上一步中的数据是server端过来的数据。只是在http连接方面遇到了些小插曲
(1)我先前用的是quick-cocos2d-x-lua中封装的CCHTTPRequest的这个进行server端交互 只是不如愿 由于server端过来的数据中是protobuf进行处理过的数据 在进行调试跟踪后发现过来的数据中不定什么地方都有\0结束符 这个导致直接在lua中调研CCHTTPRequest中的获取string 方法数据被截断不能正常解析 我在CCHTTPRequest::getResponseString进行处理过来的数据处理掉\0 也不行
(2)因为项目中要用的短连接socket我先前已经集成好luasocket。事实上这个开源的socket非常好用 也有对http的支持果断用这个測试下server端回来的数据 让我小小喜悦了一下 丢到protobuf.decode中进行解析正是我要的数据 只是有个不好的地方 luasocket对socket有设置一个超时时间 就能够不堵塞线程 可是htpp方式我找遍了站点上的资料也没找到非堵塞式的 只是这个没关系比較能够正常跑protobuf了 集成一个线程框架就ok了呀 能够用协同线程 或者是lua
llthreads 自己选择吧假设要用 luasocket的http 先附上luasocket的http代码
local http = require 'socket.http'
local ltn12 = require 'ltn12'
response_body = ""
request_body = "" function http.post(u)
local t = {}
local r, c, h = http.request{
url = u,
method = "POST",
headers = {
["Content-Type"] = "application/x-protobuf",
["Content-Length"] = #request_body,
},
source = ltn12.source.string(request_body),
sink = ltn12.sink.table(t)}
return r, c, h, t
end -- url = "http://www.baidu.com"
r,c,h,body=http.post(HTTP_URL)
print(c)
if c~= 200 then
return
end
local protobuf = require "protobuf"
local buffer = CCFileUtils:sharedFileUtils():getFileData("entity/p_result_test.pb","r",0)
-- print(buffer)
protobuf.register(buffer) local t = protobuf.decode("com.sj.web.proto.Result", body[1])
cclog(t)
(3)只是我没实用上面中提到的luasocket http 个人感觉还是直接用coco2d-x中的CCHttpClient比較好用也不用处理线程的东西 由于我通过这个測试过c++层中protobuf进行解析是全然没问题的所以我就模仿(1)中提到的CCHTTPRequest对cocos2d::extension::CCHttpClient封装使用只是有点不顺利数据传到lua层还是不正常。我就进行对\0 进行处理 处理获取的server数据例如以下
又让我喜悦了
std::vector<char> *data = response->getResponseData();
std::stringstream mystream;
for(int i=0;i<data->size();i++){
//if ((*data)[i] != '\0') {
mystream << (*data)[i];
//}else{
// mystream << '\b';
//}
}
mResponseData = mystream.str(); std::cout << mystream.str() << std::endl;
CCLog("ddd:%s",mystream.str().c_str());
CCString * cstr = CCString::create(temp);
// com::sj::web::proto::Result *r = new com::sj::web::proto::Result::Result();
// r->ParseFromString(temp.c_str());
// CCLog("ParseFromString:::::::::%d %s",r->resultcode(),r->release_major()->majorcode().c_str());
CCLuaValueDict dict;
dict["request"] = CCLuaValue::ccobjectValue(this, "HTTPRequest");
dict["data"] = CCLuaValue::stringValue(mystream.str()); // 传值回到lua层
dict["dataCString"] = CCLuaValue::ccobjectValue(cstr, "CCString");
dict["dddd"] = CCLuaValue::stringValue("dssddsdsds"); LUA_FUNCTION listener = (LUA_FUNCTION)response->getHttpRequest()->getUserData();
CCLuaStack *stack = CCLuaEngine::defaultEngine()->getLuaStack();
stack->clean();
stack->pushCCLuaValueDict(dict);
做好上一步进行改动cocos2d-x CCLuaStack.cpp 方法pushCCLuaValue(....) 中 代码293行代码。改动例如以下(这样做能够直接使用 lua_pushlstring(m_state, stringValue, length) 把全部数据压到lua上层)
return pushString(value.stringValue().c_str(), value.stringValue().length());
完整方法代码为:
void CCLuaStack::pushCCLuaValue(const CCLuaValue& value)
{
const CCLuaValueType type = value.getType();
if (type == CCLuaValueTypeInt)
{
return pushInt(value.intValue());
}
else if (type == CCLuaValueTypeFloat)
{
return pushFloat(value.floatValue());
}
else if (type == CCLuaValueTypeBoolean)
{
return pushBoolean(value.booleanValue());
}
else if (type == CCLuaValueTypeString)
{
return pushString(value.stringValue().c_str(), value.stringValue().length()); //pushString(value.stringValue().c_str());
}
else if (type == CCLuaValueTypeDict)
{
pushCCLuaValueDict(value.dictValue());
}
else if (type == CCLuaValueTypeArray)
{
pushCCLuaValueArray(value.arrayValue());
}
else if (type == CCLuaValueTypeCCObject)
{
pushCCObject(value.ccobjectValue(), value.getCCObjectTypename().c_str());
}
}
好了就介绍到这里吧希望对cocos2d-x lua 开发的同行们有所帮助 假设有什么好的protobuf对cocos2d-x lua 的支持 或者是更方便的集成 也请贡献给我一份哟 谢谢
本人用风云的pbc 心得 总的来说还算能够
1)浮点类型:java—>lua 没问题。lua—>java 没通过。
我们后端用的java 预计是lua对number浮点数类型进行decode的 有整形进行传递的时候导致没有进行对浮点类型转换(或者java对类型比較严格导致解码的时候对高地位转换失败所致) 因为开发效率前后端改成string进行传递(測试过protoc-gen-lua 也有这个问题)如有朋友能使用lua—>java进行浮点类型通信OK 迫切滴希望您共享我一份解决方式
2)枚举类型 proto文件里序号从1開始计数 否则pbc pb文件载入失败
3)上面提到的载入pb文件的时候ios win 也能够依据 CCFileUtils获取pb文件路径后用 lua io进行注冊,測试android(我还是用上面提到的方法进行读文件)用这样的方式没成功 应该是路径和权限问题导致(已经验证过是android中读取文件路径问题,我的方式是把proto写到本地后lua用io进行读取ok)读不到文件
--其它平台
local filePath = CCFileUtils:sharedFileUtils():fullPathForFilename("entity/p_result.pb")
local addr = io.open(filePath,"rb")
protobuffer = addr:read "*a"
addr:close()
protobuf.register(protobuffer
-- android例如以下
local filePath = callJava()
local addr = io.open(filePath,"rb")
protobuffer = addr:read "*a"
addr:close()
protobuf.register(protobuffer)
近期Google产品及服务全面禁封 表示对国内互联网管控的表示吐槽 可是好的技术成果是无界的(我对protobuf的使用一如既往。如有想用的。请代理去下载吧) 对protobuf的使用总结
1)发现传输数据上字节上特别节省轻量,从这个优势上传输速度明显快过其它如json,尤其适合游戏通信,假设是考虑到用户通信流量及带宽资源节省问题能够考虑
2)一点不好就是客户输出数据不全预计是pbc反序列化优化table对象问题 (和后端交互数据全靠java写的小client日志输出查看,仅仅是为了方便查看后端返回数据) 然后回lua项目进行处理信息
cocos2d-x lua 中使用protobuf并对http进行处理的更多相关文章
- 在lua环境中使用protobuf
最近在cocos2dx的项目中,需要在LUA脚本层使用protobuf协议.官方已经推出了很多种语言的版本.但唯独LUA版本不全.于是开始研究protobuf在LUA下的实现,将完整的过程记录了下来, ...
- lua 中protobuf repeated 嵌套类 复合类型
PB基础知识科普 syntax = "proto2"; package PB; message Item { required string name = ; } message ...
- cocos2d-x 2.2.0 如何在lua中注册回调函数给C++
cocos2d-x内部使用tolua进行lua绑定,但是引擎并没有提供一个通用的接口让我们可以把一个lua函数注册给C++层面的回调事件.翻看引擎的lua绑定代码,我们可以仿照引擎中的方法来做.值得吐 ...
- lua中打印所以类型功能实现table嵌套table
lua中打印所以类型功能实现 本人測试 number.string.bool.nil.table嵌套table.userdata没问题 共享一下有什么问题请拍砖 代码例如以下 cclog = func ...
- cocos2dx lua中异步加载网络图片,可用于显示微信头像
最近在做一个棋牌项目,脚本语言用的lua,登录需要使用微信登录,用户头像用微信账户的头像,微信接口返回的头像是一个url,那么遇到的一个问题就是如何在lua中异步加载这个头像,先在引擎源码里找了下可能 ...
- cocos2d-x 3.0 在lua中调用自定义类
环境 windows8, cocos2d-x 3.0, 现在开始安装需要的一些其它包 1. 按README.mdown文档上面要求的, 下载在windows下要安装的东东, 主要就是python2.7 ...
- cocos2d-x lua中实现异步加载纹理
原文地址: http://www.cnblogs.com/linchaolong/p/4033118.html 前言 问题:最近项目中需要做一个loading个界面,界面中间有一个角色人物走动的 ...
- 在Wcf中应用ProtoBuf替代默认的序列化器
Google的ProtoBuf序列化器性能的牛逼已经有目共睹了,可以把它应用到Socket通讯,队列,Wcf中,身为dotnet程序员一边期待着不久后Grpc对dotnet core的支持更期待着Wc ...
- lua中基类和“继承机制”
基类:基类定义了所有对于派生类来说普通的属性和方法,派生类从基类继承所需的属性和方法,且在派生类中增加新的属性和方法. 继承:继承是C++语言的一种重要机制,它允许在已定义的类的基础上产生新类. lu ...
随机推荐
- [暑假集训--数位dp]LightOj1205 Palindromic Numbers
A palindromic number or numeral palindrome is a 'symmetrical' number like 16461 that remains the sam ...
- hdu 3501 容斥原理或欧拉函数
Calculation 2 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Tot ...
- Pushlets的初始化陷阱
Pushlets是在类名为Pushlet的servlet的init方法中进行初始化的.一般我们会在web.xml配置pushlet的时候,指定其servlet在Web应用启动时就进行初始化,即便这样, ...
- CI安全
URI安全,CodeIgniter 严格限制 URI 中所能包含的字符,以此帮助你设计的程序减少被恶意数据入侵的可能.URI 一般只包含下列内容: 字母和数字(Alpha-numeric text) ...
- poj 2253(kruskal)
Frogger Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 34968 Accepted: 11235 Descrip ...
- LeetCode OJ--Binary Tree Postorder Traversal
http://oj.leetcode.com/problems/binary-tree-postorder-traversal/ 树的后序遍历,可以使用递归,也可以使用栈,下面是栈的实现代码 #inc ...
- python笔记2:函数
5. 函数 Python函数代码块以 def 关键词开头; 函数内容以冒号起始,并且缩进. *注: python中,strings, tuples, 和 numbers 是不可更改的对象,而 list ...
- React项目的打包与部署到腾讯云
腾讯云送了30天的免费试用,于是有了把react项目部署到上面的想法.项目是默认生成的,只是一个页面,但是这个过程中也遇到了不少麻烦与问题.下面来具体梳理下: create-react-app 来自F ...
- 移动端自动化测试(一)appium环境搭建
自动化测试有主要有两个分类,接口自动化和ui自动化,ui自动化呢又分移动端的和web端的,当然还有c/s架构的,这种桌面程序应用的自动化,使用QTP,只不过现在没人做了. web自动化呢,现在基本上都 ...
- 计蒜客 UCloud 的安全秘钥(随机化+Hash)
题目链接 UCloud 的安全秘钥 对于简单的版本,我们直接枚举每个子序列,然后sort一下判断是否完全一样即可. #include <bits/stdc++.h> using names ...