首页 > 其他分享 >cocos2d-x 3.1 集成 云风pbc

cocos2d-x 3.1 集成 云风pbc

时间:2022-12-27 11:37:43浏览次数:39  
标签:pbc .. manual lua external cocos2d cpp 云风


cocos2d-x 3.x版本变动比较大,从改用cmake管理整个项目,到使用python集成一体化的项目工具。这些都是我喜欢的,我可以很容易的在我的ubuntu上面搭建环境,而且根本就不用考虑IDE的事情,sublime-text or emacs足矣。唯一需要自己动手的就是制作一个比较好的调试工具。我是使用lua+cplusplus开发,所以调试就比较的难受,暂时只能这样,后面考虑自己实现一个远程lua调试工具。触控有发布一款IDE,可是目前没有linux平台的版本,我想以后也不会做的,所以就干脆胡忽略了吧。下面就说一下如何在cocos2d-x 3.1里面集成pbc吧。

网上有关于如何在quick-cocos2dx里面集成pbc的,不过quick和cocos2d-x的lua集成方式不一样,而且3.x的版本在安卓平台使用的是luajit,不过在开发者方面还是和lua一样,这只是为了提高效率。可以简单的看一下pbc中的lua binding下面的makefile,也是可以使用luajit的。如果对luajit感兴趣,那么就自己去搜罗吧。网上的这些关于集成pbc的文章,我有粗略的看过一些,结合cocos2d-x 3.x的情况,参考意义并不大,下面我也会给出我自己的做法。

我大三的时候写过一篇关于如何在cocos2d-x中集成luasocket的文章,应该也算是比较早的了。不过,那篇文章的做法,在现在看来的确不是什么好方法,不值得推荐。cocos2dx从2.x的某个版本就添加了自己的lua loader,用来加载lua engine运行的脚本,具体可参考Cocos2dxLuaLoader.cpp/.h文件中的函数。



1  int cocos2dx_lua_loader(lua_State *L)
2 {
3 std::string filename(luaL_checkstring(L, 1));
4 size_t pos = filename.rfind(".lua");
5 if (pos != std::string::npos)
6 {
7 filename = filename.substr(0, pos);
8 }
9
10 pos = filename.find_first_of(".");
11 while (pos != std::string::npos)
12 {
13 filename.replace(pos, 1, "/");
14 pos = filename.find_first_of(".");
15 }
16 filename.append(".lua");
17
18 Data data = FileUtils::getInstance()->getDataFromFile(filename);
19
20 if (!data.isNull())
21 {
22 if (luaL_loadbuffer(L, (char*)data.getBytes(), data.getSize(), filename.c_str()) != 0)
23 {
24 luaL_error(L, "error loading module %s from file %s :\n\t%s",
25 lua_tostring(L, 1), filename.c_str(), lua_tostring(L, -1));
26 }
27 }
28 else
29 {
30 log("can not get file data of %s", filename.c_str());
31 }
32
33 return 1;
34 }



如果想要实现对自己项目的lua脚本进行解密或者是解压缩处理,都可以在这里下一点功夫。会有不错的收获,这部分我在后面也会做,不过还在写加密算法中,还要再等等。 - -

也许我这里给出的函数只是个开始,准确的说应该是个错误的开始,不要尝试从这里思考。为什么? 因为cocos2d-x修改了lua的文件加载器。具体的原因是lua在5.1版本以后完善了管理机制,

采用统一的require加载,这也不难在cocos2d-x里面看出来,可以随便看看Lua引擎入口加载执行的函数,如下:(CCLuaStack.cpp)



1 int LuaStack::executeScriptFile(const char* filename)
2 {
3 #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
4 std::string code("require \"");
5 code.append(filename);
6 code.append("\"");
7 return executeString(code.c_str());
8 #else
9 std::string fullPath = FileUtils::getInstance()->fullPathForFilename(filename);
10 ++_callFromLua;
11 int nRet = luaL_dofile(_state, fullPath.c_str());
12 --_callFromLua;
13 CC_ASSERT(_callFromLua >= 0);
14 // lua_gc(_state, LUA_GCCOLLECT, 0);
15
16 if (nRet != 0)
17 {
18 CCLOG("[LUA ERROR] %s", lua_tostring(_state, -1));
19 lua_pop(_state, 1);
20 return nRet;
21 }
22 return 0;
23 #endif
24 }



如果你需要写自己的脚本资源管理模块,那么这里就需要注意了,在android和其他平台处理的时候有明显的不同,不过仅仅是在入口的不同,在后续的require加载中都是一样的,因为在注册

lua loader(也就是上面的cocos2dx_lua_loader)是一样的。 - - 当作一个友善的提示吧。然而lua本身提供的lua loader有四个,用于加载,在Lua源码下的loadlib.c中可以找到:


1 static const lua_CFunction loaders[] =
2 {loader_preload, loader_Lua, loader_C, loader_Croot, NULL};


对应luajit中也是可以找到的.源码在luajit源码目录下的lib_package.c中:



1 static const lua_CFunction package_loaders[] =
2 {
3 lj_cf_package_loader_preload,
4 lj_cf_package_loader_lua,
5 lj_cf_package_loader_c,
6 lj_cf_package_loader_croot,
7 NULL
8 };



经过cocos2d-x修改loader之后,lua在加载c lib的时候就有问题了,加载不到。不过,还是可以通过修改lua的环境表来做到加载pbc。具体做法如下,修改lua_extension.c:



1 #include "pbc-master/src/pbc-lua.h" //add
2
3 static luaL_Reg luax_exts[] = {
4 {"socket.core", luaopen_socket_core},
5 {"mime.core", luaopen_mime_core},
6 {"protobuf.c", luaopen_protobuf_c}, // add
7 {NULL, NULL}
8 };
9
10 void luaopen_lua_extensions(lua_State *L)
11 {
12 // load extensions
13 luaL_Reg* lib = luax_exts;
14 lua_getglobal(L, "package");
15 lua_getfield(L, -1, "preload");
16 for (; lib->func; lib++)
17 {
18 lua_pushcfunction(L, lib->func);
19 lua_setfield(L, -2, lib->name);
20 }
21 lua_pop(L, 2);
22 }



将下载的pbc源码(如果是http下载的话那应该是pbc-master,如果是git clone的话那就是pbc)放到coco/lua目录下面去,将binding下面的pbc-lua.c拷贝到src目录下面,将pbc.h也同样拷贝过去,

然后在创建一个pbc-lua.h文件,内容就是luaopen_protobuf_c的函数声明,如下:



1 #ifndef PBC_LUA_H
2 #define PBC_LUA_H
3
4 #ifdef __cplusplus
5 extern "C" {
6 #endif
7
8 extern int luaopen_protobuf_c(lua_State *L);
9
10 #ifdef __cplusplus
11 }
12 #endif
13
14 #endif/* PBC_LUA_H */



由于目标平台是安卓,所以下面就去修改ndk的Android.mk文件,目标就是coco/scripting/lua-bindings下面的Android.mk文件: 修改的部分如下:



1 LOCAL_SRC_FILES := manual/CCLuaBridge.cpp \
2 manual/CCLuaEngine.cpp \
3 manual/CCLuaStack.cpp \
4 manual/lua_debugger.c \
5 manual/CCLuaValue.cpp \
6 manual/Cocos2dxLuaLoader.cpp \
7 manual/CCBProxy.cpp \
8 manual/Lua_web_socket.cpp \
9 manual/LuaOpengl.cpp \
10 manual/LuaScriptHandlerMgr.cpp \
11 manual/LuaBasicConversions.cpp \
12 manual/LuaSkeletonAnimation.cpp \
13 manual/lua_cocos2dx_manual.cpp \
14 manual/lua_cocos2dx_extension_manual.cpp \
15 manual/lua_cocos2dx_coco_studio_manual.cpp \
16 manual/lua_cocos2dx_ui_manual.cpp \
17 manual/lua_cocos2dx_spine_manual.cpp \
18 manual/lua_cocos2dx_physics_manual.cpp \
19 manual/lua_cocos2dx_deprecated.cpp \
20 manual/lua_xml_http_request.cpp \
21 manual/platform/android/CCLuaJavaBridge.cpp \
22 manual/platform/android/jni/Java_org_cocos2dx_lib_Cocos2dxLuaJavaBridge.cpp \
23 manual/tolua_fix.cpp \
24 manual/lua_extensions.c \
25 auto/lua_cocos2dx_auto.cpp \
26 auto/lua_cocos2dx_extension_auto.cpp \
27 auto/lua_cocos2dx_studio_auto.cpp \
28 auto/lua_cocos2dx_ui_auto.cpp \
29 auto/lua_cocos2dx_spine_auto.cpp \
30 auto/lua_cocos2dx_physics_auto.cpp \
31 ../../../external/lua/tolua/tolua_event.c \
32 ../../../external/lua/tolua/tolua_is.c \
33 ../../../external/lua/tolua/tolua_map.c \
34 ../../../external/lua/tolua/tolua_push.c \
35 ../../../external/lua/tolua/tolua_to.c \
36 ../../../external/lua/luasocket/auxiliar.c \
37 ../../../external/lua/luasocket/buffer.c \
38 ../../../external/lua/luasocket/except.c \
39 ../../../external/lua/luasocket/inet.c \
40 ../../../external/lua/luasocket/io.c \
41 ../../../external/lua/luasocket/luasocket.c \
42 ../../../external/lua/luasocket/mime.c \
43 ../../../external/lua/luasocket/options.c \
44 ../../../external/lua/luasocket/select.c \
45 ../../../external/lua/luasocket/serial.c \
46 ../../../external/lua/luasocket/tcp.c \
47 ../../../external/lua/luasocket/timeout.c \
48 ../../../external/lua/luasocket/udp.c \
49 ../../../external/lua/luasocket/unix.c \
50 ../../../external/lua/luasocket/usocket.c \
51 ../../../external/lua/pbc-master/src/alloc.c \ -- begin
52 ../../../external/lua/pbc-master/src/array.c \
53 ../../../external/lua/pbc-master/src/bootstrap.c \
54 ../../../external/lua/pbc-master/src/context.c \
55 ../../../external/lua/pbc-master/src/decode.c \
56 ../../../external/lua/pbc-master/src/map.c \
57 ../../../external/lua/pbc-master/src/pattern.c \
58 ../../../external/lua/pbc-master/src/proto.c \
59 ../../../external/lua/pbc-master/src/register.c \
60 ../../../external/lua/pbc-master/src/rmessage.c \
61 ../../../external/lua/pbc-master/src/stringpool.c \
62 ../../../external/lua/pbc-master/src/varint.c \
63 ../../../external/lua/pbc-master/src/wmessage.c \
64 ../../../external/lua/pbc-master/src/pbc-lua.c \ -- end



之后就不需要任何的修改了,也不需要在c++代码部分手动去加载pbc的库,因为一切都已经昨晚了。可以很容易的看出来,这种做法的好处。PS:最后别忘记将protobuf.lua拷贝到你的src或者是res下面,都是可以的,这个就不需要解释了。

测试是我将addressbook.pb拷贝到src目录下面,在AppDelegate.cpp中添加了比较简单的拷贝代码,将addressbook.pb拷贝到writablepath,原因就是后面我使用了lua io库去读pb文件,这也是直接参考pbc中的小例子写的,如果有更好的做法请告诉我。谢谢。



1  ssize_t __len = 0;
2 auto writablepath = FileUtils::getInstance()->getWritablePath()+"addressbook.pb";
3 unsigned char *data = FileUtils::getInstance()->getFileData("assets/src/addressbook.pb","r",&__len);
4
5 FILE *fp = fopen(writablepath.c_str(),"w");
6 fwrite(data,sizeof(char),__len,fp);
7 fclose(fp);
8 delete[] data;
9 data = NULL;



下面我给出lua部分的测试代码,实际运行是通过的,我的环境是ubuntu 14.04 x64 + ndk r9 + android



1     local tf = cc.Label:create()
2 tf:setString(package.loaded)
3
4 local writablepath = cc.FileUtils:getInstance():getWritablePath()
5
6 local addr = io.open(writablepath .. "addressbook.pb", "rb")
7 local buffer = addr:read "*a"
8 addr:close()
9 protobuf.register(buffer)
10
11 local t = protobuf.decode("google.protobuf.FileDescriptorSet", buffer)
12 local proto = t.file[1]
13
14 tf:setString(proto.name .. " " .. proto.package)
15
16
17 local addressbook = {
18 name = "Alice",
19 id = 12345,
20 phone = {
21 { number = "1301234567" },
22 { number = "87654321", type = "WORK" },
23 }
24 }
25
26 local code = protobuf.encode("tutorial.Person", addressbook)
27
28 local decode = protobuf.decode("tutorial.Person" , code)
29
30 tf:setString(decode.name .. " | " .. decode.id)



我使用FileUtils:getInstance():getFileData无法获取数据,所以也就改为在C++那边拷贝,知道这部分如何使用的可以告诉我,先谢过。



标签:pbc,..,manual,lua,external,cocos2d,cpp,云风
From: https://blog.51cto.com/u_15923385/5971833

相关文章