网络游戏在前后端交换的过程中,有可能会有大量的数据,比如说游戏回放功能,这时最好是将数据压缩一下。
比较简单的数据压库就是zlib了。
zlib官方文档,常用的函数都在这里了,解释很详细。
一 C++功能实现部分
下面将代码贴上来。
在ZipUtils中添加下面三个函数:
// ZipUtils.h
<pre name="code" class="cpp">typedef struct{ unsigned str_size; unsigned buf_size; char data[];// 柔性数组 }CompressedData; class ZipUtils { public: // add by XuLidong static void testFun(); static unsigned getCompressBound(unsigned len); static bool compressString(const char* str,CompressedData* pdata); static bool decompressString(CompressedData* pdata, char* str); };
用到了柔性数组,不动的可以参考我的另一篇文章
下面是相应的实现:
// ZipUtils.cpp
#include <zlib.h> #include <stdlib.h> #include "ZipUtils.h" int test1() { char text[] = "zlib compress and uncompress test\[email protected]\n2012-11-05\n"; uLong tlen = strlen(text) + 1; /* 需要把字符串的结束符'\0'也一并处理 */ char* buf = NULL; uLong blen; /* 计算缓冲区大小,并为其分配内存 */ blen = compressBound(tlen); /* 压缩后的长度是不会超过blen的 */ printf("compress str_size:%d, buf_size:%d\n", tlen, blen); if((buf = (char*)malloc(sizeof(char) * blen)) == NULL) { printf("no enough memory!\n"); return -1; } /* 压缩 */ if(compress((Bytef*)buf, &blen, (const Bytef*)text, tlen) != Z_OK) { printf("compress failed!\n"); return -1; } /* 解压缩 */ printf("uncompress str_size:%d, buf_size:%d\n", tlen, blen); if(uncompress((Bytef*)text, &tlen, (const Bytef*)buf, blen) != Z_OK) { printf("uncompress failed!\n"); return -1; } /* 打印结果,并释放内存 */ printf("%s", text); if(buf != NULL) { free(buf); buf = NULL; } } void test2() { const char* str="abcdefg 中文字符可以吗 ? 》 , >\ "; unsigned len = strlen(str) + 1; unsigned long blen = compressBound(len); CompressedData* pdata = (CompressedData*)malloc(sizeof(CompressedData) + blen * sizeof(char)); pdata->str_size = len; pdata->buf_size = blen; ZipUtils::compressString(str, pdata); char* ustr = (char*)malloc(len); memset(ustr, 0, len); ZipUtils::decompressString(pdata, ustr); free(ustr); } void ZipUtils::testFun() { //test1(); test2(); } unsigned ZipUtils::getCompressBound(unsigned len) { return (unsigned)compressBound((unsigned long)len); } bool ZipUtils::compressString(const char* str, CompressedData* pdata) { printf("compress string:%s\n", str); int res = compress((Bytef*)pdata->data, (unsigned long*)&(pdata->buf_size), (const Bytef*)str, (unsigned long)pdata->str_size); if( res != Z_OK) { printf("compress failed, error code:%d\n", res); return false; } printf("string size %d, buffer size: %d\n", pdata->str_size, pdata->buf_size); return true; } bool ZipUtils::decompressString(CompressedData* pdata, char* str) { printf("string size %d, buffer size: %d\n", pdata->str_size, pdata->buf_size); int res = uncompress((Bytef*)str, (unsigned long *)&(pdata->str_size), (const Bytef *)pdata->data, (unsigned long)pdata->buf_size); if(res != Z_OK) { printf("uncompress failed, error code:%d\n", res); return false; } printf("uncompress string:%s\n", str); return true; }
二 C++导出到Lua接口
// ZipUtilsLua.h
#include "tolua++.h" #include "tolua_event.h" #include "lauxlib.h" int tolua_ZipUtils_open(lua_State *L);
// ZipUtilsLua.cpp
#include "support/zip_support/ZipUtils.h" #include <string> #include "tolua++.h" #include "tolua_event.h" #include "lauxlib.h" using namespace cocos2d; int TOLUA_API luaCopressString(lua_State *L) { size_t slen = 0; const char *str = lua_tolstring(L, 1, &slen); unsigned blen = ZipUtils::getCompressBound((unsigned long)slen); CompressedData* pdata = (CompressedData*)malloc(sizeof(CompressedData) + blen * sizeof(char)); pdata->str_size = slen; pdata->buf_size = blen; if(ZipUtils::compressString(str, pdata)){ lua_pushlstring(L, (char*)pdata, pdata->buf_size+sizeof(CompressedData)); printf("sizeof=%d", sizeof(CompressedData)); } else{ lua_pushstring(L, ""); } free(pdata); return 1; } int TOLUA_API luaDecopressString(lua_State *L) { const char *strBuf = lua_tostring(L, 1); CompressedData* pdata = (CompressedData*)strBuf; unsigned slen = pdata->str_size; unsigned blen = pdata->buf_size; char* str = (char*)malloc(pdata->str_size * sizeof(char)); if(ZipUtils::decompressString(pdata, str)){ lua_pushlstring(L, str, slen); } else{ lua_pushstring(L, ""); } free(str); return 1; } int TOLUA_API luaTestFun(lua_State *L) { ZipUtils::testFun(); return 1; } static luaL_Reg ziplib[] = { {"compress", luaCopressString}, {"decompress", luaDecopressString}, {"testFun", luaTestFun}, {NULL, NULL} }; // 函数名必须为luaopen_xxx,其中xxx表示library名称,Lua代码require "xxx"需要与之对应。 int luaopen_ZipUtils(lua_State* L) { const char* libName = "ZipUtils"; luaL_register(L, libName, ziplib);// 调用方式libName.函数名 return 1; } int tolua_ZipUtils_open(lua_State *L) { luaopen_ZipUtils(L); return 1; }
注册代码:
// register lua engine CCLuaEngine* pEngine = CCLuaEngine::defaultEngine(); CCScriptEngineManager::sharedManager()->setScriptEngine(pEngine); <span style="font-family: Arial, Helvetica, sans-serif;">tolua_ZipUtils_open</span><span style="font-family: Arial, Helvetica, sans-serif;">(pEngine->getLuaStack()->getLuaState());</span>
三 Lua中调用
require ("ZipUtils") local string = "hello, world" local zipData = ZipUtils.compress(string) if c ~= "" then print("XXXXXXXXXXXXXXXXX compress", zipData) else print("XXXXXXXXXXXXXXXXX error") end local str = ZipUtils.decompress(zipData) if str ~= "" then print("XXXXXXXXXXXXXXXXX decompress", str) else print("XXXXXXXXXXXXXXXXX error") end
时间: 2025-01-02 01:13:16