Using Protobuf in cocos2d-x lua and handling http
This article describes the use of HTTP and Cocos2d-x-based encapsulation of Lua HTTP in cocos2d-x Lua (partial OK)
This blog link
http://blog.csdn.net/vpingchangxin/article/details/24458051
Protobuf Google a very good package of data transmission to tell the truth, Google's things are actually better than that, so we have to use him for the back-and-forth data exchange. It's just that Google didn't support Lua. The community has open-source heroes who have contributed to all of the LUA PROTOBUF I just found the cloud-wind of the PBC changes in the relevant cocos2d-x classes in the normal use. Protoc-gen-lua I used to always report truncation data after changing the class in the cocs2d-x after the Protoc-gen-lua is not tested whether this problem caused
1) Integrated Cloud Hero's (blog) LUA-PBC standard C written protobuf detailed look at the PBC's help very easy to integrate
2) Generate PB files (I wrote my own batch in Mac to generate all. proto files for. pb files) to add Pb and proto files to project resources
#!/bin/sh#pb = "PB" For I in *.protodo#echo $i #echo ${i%.*} ". Pb" #echo ${i%.*} #pbn = $i | cut-d.pbname=${i%.*} ". Pb" #echo $pbn #echo $pbnameprotoc--descriptor_set_out $pbname $idoneecho "Finish"
Can also be manually generated using the command line
Protoc--descriptor_set_out AAA.PB Aaa.proto
3)This step can be ignored, can be directly read with Io (Android is the path problem, see the following explanation of this article)use in Lua such as the following code (I use Cocos2d-x in the binding of the ccfileutils in the way to get the file, just to manually use tolua++ to bind to Lua, can refer to my last article of the binding method, the master of the Cloud in Lua IO form acquisition in the relevant understanding can not cross the platform of all the use of this)
Local PROTOBUF = require "protobuf" Local buffer = Ccfileutils:sharedfileutils (): Getfiledata ("ENTITY/P_RESULT.PB" , "R", 0) --Print (buffer) protobuf.register (buffer)
4)This step can be ignored. Able to read directly with Io (Android is the path problem please see the following explanation in this article)after the last step, we have to make changes to the class mentioned in the CCFileUtils.cpp, assuming that the read file PB file will not be changed when the bad reason is to read the file when the end always add extra bytes I am not aware of this problem changes cocos2d-x CCFileUtils.cpp The following method of reading data after processing and adding the following method to the tolua++ to bind to the LUA layer
Change CCFILEUTILS.CP getfiledata (const Char* pszfilename, const Char* pszmode, Unsignedlong * pSize) method (in the end, add. Ensure that bytes are not redundant) such as the following code
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]! = ' + ') pbuffer[*psize] = ' + '; if (! pbuffer) {std::string msg = "Get data from File ("; Msg.append (pszFileName). Append (") failed!"); Cclog ("%s", Msg.c_str ()); } return pbuffer;}
5) After the last step, the LUA layer is basically done to create the local data and encode it to the server side, such as the following code
Local major = { Majorid = "795f94a9-3466-41b4-bf16-043ba8081fab" } Local buffer = Protobuf.encode (" Com.sj.web.proto.Major ", Major)
6) Our client transmits the data to the server side server side will return the data to us the same we receive the data certainly also protobuf the data to use the Protobuf.decode to solve the data
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) The data in the previous step is the server-side data. Just a little episode in the HTTP connection.
(1) I used to Quick-cocos2d-x-lua in the package of Cchttprequest this server-side interaction is just not desirable because the server side of the data is protobuf processed data After the debug trace is found in the data, there is no place in the end of the word. This results in the acquisition of a string method in the Cchttprequest directly in Lua. I'm in Cchttprequest:: The data processed by getresponsestring is not going to work.
(2) Because of the short connection socket I have previously integrated the Luasocket. In fact, this open source socket is very useful and has the support of HTTP decisive with this test of the server back to the data to let me a little joy to be thrown into the protobuf.decode to parse it's just the data I need is a bad place. Luasocket to the socket has a timeout time can not plug the thread but HTPP way I looked all over the site of the data also did not find the non-clogging type of just this does not matter more normal run protobuf the integration of a threaded framework is OK AH can be used with a collaborative thread or LUA Llthreads choose it. Assume that you want to attach Luasocket HTTP code with Luasocket HTTP first
Local HTTP = require ' socket.http ' local ltn12 = Require ' ltn12 ' response_body = "" request_body = " func tion 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~= and 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) I'm just not practical. The above mentioned Luasocket HTTP personal feeling or directly with the coco2d-x in the cchttpclient is more useful and do not have to deal with the thread of things because I passed this test C + + The protobuf in the layer is completely fine, so I'm going to imitate (1) The cchttprequest that is mentioned in the cocos2d::Extension::The Cchttpclient package uses just a little bit of a smooth data upload to the LUA layer or not.I'm just going to have to deal with it and make me happy.Processing the obtained server data such as the following
std::vector<char> *data = Response->getresponsedata (); Std::stringstream MyStream; for (int i=0;i<data->size (); i++) {//if ((*data) [i]! = ' + ') {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::p roto::result *r = new Com::sj::web::p Roto::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 ()); Transfer value back to LUA layer dict["datacstring" = Ccluavalue::ccobjectvalue (CStr, "ccstring"); dict["dddd"] = Ccluavalue::stringvalue ("Dssddsdsds"); LUA_function listener = (lua_function) response->gethttprequest ()->getuserdata (); Ccluastack *stack = ccluaengine::d efaultengine ()->getluastack (); Stack->clean (); Stack->pushccluavaluedict (DICT);
Do the previous step to change the Cocos2d-x CCLuaStack.cpp method Pushccluavalue (...) in code 293 lines of code. Changes such as the following (this allows you to directly use lua_pushlstring(m_state, stringvalue, length) to press all the data to the upper Lua)
Return pushstring (Value.stringvalue (). C_STR (), Value.stringvalue (). Length ());
The full method code is:
void Ccluastack::p ushccluavalue (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 ());} }
All right, here we go. Hopefully, it's helpful to cocos2d-x LUA developers. Suppose there's any good protobuf support for cocos2d-x LUA or more convenient integration please contribute to me.
I use the situation of the PBC's experience in general still can
1) floating-point type: Java->lua no problem. Lua->java didn't pass.
Our backend Java is expected to be Lua's decode of number floating-point number types, resulting in no conversion to the floating-point type (or to a high-status conversion failure when the Java pair type is more tightly decoded) Because the development efficiency before and after the end of the change to a string to pass (tested Protoc-gen-lua also have this problem) if a friend can use Lua->java for floating-point type communication OK, I want you to share my solution
2) enumeration type proto file sequence number starting from 1 or the PBC PB file fails to load
3) When loading PB files mentioned above, iOS win can also use LUA IO to register after obtaining PB file path according to Ccfileutils, test Android (I still read the file using the method mentioned above) in such a way not success should be caused by path and permission problem ( It has been verified that the file path problem is read in Android, my way is to write Proto to the local after Lua read with IO OK) cannot read the file
--other platforms 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 For example the following local FilePath = Calljava () Local addr = Io.open (FilePath, "RB") Protobuffer = addr:read "*a " Addr:close () protobuf.register (Protobuffer)
Recent Google products and services to prohibit the full ban on the domestic Internet control of the expression of spit groove but good technical results are unbounded (my use of protobuf as always. If you want to use it. Please agent to download it) summary of the use of PROTOBUF
1) The discovery of the transmission of data on the byte on the special saving of light, from the advantage of transmission speed significantly faster than other such as JSON, especially suitable for game communication, assuming that the user traffic and bandwidth resource saving problems can be considered
2) A little bad is the customer output data is not fully expected to be the PBC deserialization Optimization Table object problem (and back-end interactive data by the Java-written small client log output view, just to facilitate viewing back-end data) and then back to the LUA project to process information
Using Protobuf in Cocos2d-x Lua and handling HTTP