Cocos2d-x in Lua using PROTOBUF and processing HTTP
This article describes the use of HTTP and Cocos2d-x to LUA HTTP encapsulation (partially OK) in Cocos2d-x Lua
This blog link
http://blog.csdn.net/vpingchangxin/article/details/24458051
Protobuf Google's a very good use of the package to transmit data to tell the truth, Google's things are really easy to use, so we end data exchange with him, but Google did not support Lua. Fortunately, the community has open source heroes who have contributed to all the Lua PROTOBUF I only found Cloud Wind's PBC modify the classes in the related cocos2d-x to work properly. Protoc-gen-lua I always report the truncation of data when I'm using it. Cocs2d-x after the class in the modified Protoc-gen-lua is not tested for the problem caused
1) Integrated Cloud Master (blog) LUA-PBC standard C written protobuf specifically see the PBC help is easy to integrate
2 Generate PB file (I wrote a Mac myself batch generates all. proto files for. pb files) add both PB and proto files to the project resource
#!/bin/sh
#pb = "PB" for
i-*.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"
You can also manually build with the command line
Protoc--descriptor_set_out AAA.PB Aaa.proto
3 This step can be ignored, you can read directly with Io (Android is a path problem, see the bottom of this article) use the following code in LUA (I'm using the way to get files in the ccfileutils bound in Cocos2d-x, but manually tolua++ To be bound to Lua, you can refer to the bindings in my last article, which is used in the Lua IO form in the Cloud warrior to get across the platform in the relevant knowledge.
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, you can read directly with Io (Android is the path problem, please see the bottom of this article) we have to modify the class in the mentioned CCFileUtils.cpp if you do not modify the read-file PB file will be good when the bad reason is End of reading files always add extra bytes I'm not sure about this. Modify the read data in the following method of CCFileUtils.cpp in Cocos2d-x and add the following method to the LUA layer in tolua++
Modify the CCFILEUTILS.CP getfiledata (const char* pszfilename, const char* Pszmode, unsigned long * psize) method (at the end of the add, ensure that the bytes are not redundant) the following code
unsigned char* ccfileutils::getfiledata (const char* pszfilename, const char* Pszmode, unsigned long * psize) {Unsigne
d 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 of the LUA layer basic finish can create local data and encode to the server side of the following code
Local major = {
Majorid = ' 795f94a9-3466-41b4-bf16-043ba8081fab '
} local
buffer = Protobuf.encode (" Com.sj.web.proto.Major ", Major)
6 Our client data transfer to the server side of the server will be returned to us the same data we received must also be PROTOBUF data, using Protobuf.decode to solve 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 from the previous step is the server-side data, but there are some minor episodes in the HTTP connection
(1) I used the cchttprequest in the Quick-cocos2d-x-lua package for server-side interaction, but not as much as the server-side data is PROTOBUF data. In the data that comes up after the debug trace, there's no end of it anywhere. This results in a study of the cchttprequest in Lua. Get string method data truncated cannot parse normally I am in Cchttprequest:: Getresponsestring processed data, and it's not going to work out.
(2) As a result of the project to use the short connection socket I have previously integrated luasocket, in fact, this open source socket is very easy to use with the support of HTTP decisively with this test server-side back data let me a little joy To parse it in the Protobuf.decode is exactly the data I want, but there's a bad place. Luasocket a timeout on the socket can be done without blocking the thread but HTPP the way I looked through the information on the website and I didn't find the non-blocking type. But this doesn't matter. Comparison can run protobuf the integration of a thread framework is OK ah, you can use a collaborative thread or LUA Llthreads Choose your own if you want to use Luasocket http first append luasocket http code
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~= 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) But I did not use the above mentioned in the Luasocket HTTP personal feeling or directly with the coco2d-x in the cchttpclient more useful also do not have to deal with threads of things because I passed this test C + + The protobuf in the layer is completely fine, so I'm going to imitate the cchttprequest mentioned in (1) cocos2d:: extension:: Cchttpclient encapsulation use but a little bit of not smooth data to the LUA layer is still not normal, and I'm going to I'm glad I handled it. Processing the retrieved server data is as follows
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 ());
Returns the value to the 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 modify the Cocos2d-x CCLuaStack.cpp method Pushccluavalue (...) code 293 lines of code, modify the following (this can be used directly lua_pushlstring (M_state, StringValue, length) press all data to the LUA upper level
Return pushstring (Value.stringvalue (). C_STR (), Value.stringvalue (). Length ());
The Complete 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 will help cocos2d-x LUA developers if there is any good protobuf support for cocos2d-x LUA or more convenient integration please give me a piece of yo thank you
I use the situation of PBC experience generally can be
1 floating-point type: Java->lua no problem; Lua->java failed. The Java estimate for our backend is that Lua's decode of number floating-point types is not converted to floating-point types (or because of the high status conversion failure of Java when the type is more tightly led to decoding) Since the development efficiency is changed to string for delivery (tested Protoc-gen-lua also has this problem) if a friend can use Lua->java to do floating-point type communication OK desperately want you to share my solution
2 enumeration type proto file ordinal number starting from 1 otherwise the PBC PB file failed to load
3 The above mentioned loading PB file, iOS win can also be based on ccfileutils to obtain PB file path after the use of LUA IO Register, test android (I still read the method mentioned above) in this way did not succeed It should be the path and permissions problem (which has been verified to read the file path problem in Android, my way is to write Proto to the local post Lua read OK with IO) and not 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 follows local
FilePath = Calljava () local
addr = Io.open (FilePath, "RB")
Protobuffer = Addr:read "*a"
addr:close ()
protobuf.register (Protobuffer)
Recently, Google products and services to the full ban on the domestic Internet control of the expression of spit but good technical results are unbounded (I protobuf use, as always, if you want to use, please agent to download it) on the use of PROTOBUF summary
1) found that the byte on the data transmission is particularly light, from this advantage transmission speed is significantly faster than other such as JSON, especially for game communication, if it is to take into account the user traffic and bandwidth resource savings issues can be considered
2 A bad thing is that the client output data is not full estimate is the PBC deserialization Optimization Table object problem (and back-end interactive data is Java-written small client log output view, just to facilitate viewing back-end return data) and then back to the LUA project processing information