cocos2d-x 3.x版本号变动比較大,从改用cmake管理整个项目,到使用python集成一体化的项目工具。

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

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

或许我这里给出的函数仅仅是个開始。准确的说应该是个错误的開始。不要尝试从这里思考。

为什么? 由于cocos2d-x改动了lua的文件载入器。

详细的原因是lua在5.1版本号以后完好了管理机制。

採用统一的require载入,这也不难在cocos2d-x里面看出来。能够随便看看Lua引擎入口载入运行的函数,例如以下:(CCLuaStack.cpp)

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

假设你须要写自己的脚本资源管理模块,那么这里就须要注意了。在android和其它平台处理的时候有明显的不同。不过不过在入口的不同,在兴许的require载入中都是一样的。由于在注冊

lua loader(也就是上面的cocos2dx_lua_loader)是一样的。

- - 当作一个友善的提示吧。然而lua本身提供的lua loader有四个,用于载入,在Lua源代码下的loadlib.c中能够找到:

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

相应luajit中也是能够找到的.源代码在luajit源代码文件夹下的lib_package.c中:

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

经过cocos2d-x改动loader之后,lua在载入c lib的时候就有问题了,载入不到。

只是。还是能够通过改动lua的环境表来做到载入pbc。详细做法例如以下,改动lua_extension.c:

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

将下载的pbc源代码(假设是http下载的话那应该是pbc-master,假设是git clone的话那就是pbc)放到coco/lua文件夹以下去,将binding以下的pbc-lua.c复制到src文件夹以下。将pbc.h也相同拷贝过去,

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

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

因为目标平台是安卓,所以以下就去改动ndk的Android.mk文件。目标就是coco/scripting/lua-bindings以下的Android.mk文件: 改动的部分例如以下:

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

之后就不须要不论什么的改动了。也不须要在c++代码部分手动去载入pbc的库,由于一切都已经昨晚了。能够非常easy的看出来,这样的做法的优点。PS:最后别忘记将protobuf.lua复制到你的src或者是res以下,都是能够的,这个就不须要解释了。

測试是我将addressbook.pb复制到src文件夹以下,在AppDelegate.cpp中加入了比較简单的拷贝代码,将addressbook.pb复制到writablepath,原因就是后面我使用了lua io库去读pb文件。这也是直接參考pbc中的小样例写的,假设有更好的做法请告诉我。谢谢。

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

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

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

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

pbc lua binding 文摘:http://blog.csdn.net/kaitiren/article/details/28865725


cocos2d-x 3.1 集成 云风pbc的更多相关文章

  1. 在Quick-cocos2dx中使用云风pbc解析Protocol Buffers,支持win、mac、ios、android

    本例主要介绍 如何将 pbc 集成到quick-cocos2dx框架中,让我们的cocos2dx客户端Lua拥有编解码Protocol Buffers能力. 参考: 云风pbc的用法: http:// ...

  2. 云风pbc源码alloc.c

    #include <stdlib.h> #include <stdio.h> // 用于统计内存的申请和释放次数匹配 ; void * _pbcM_malloc(size_t ...

  3. 对云风 cstring 第二次解析

    前言 从明天起 关心粮食和蔬菜 我有一所房子 面朝大海 春暖花开 本文前提条件 1.了解 posix 线程 2.了解 原子操作 3.具备简单C基础,或者 你也敲一遍. 如果上面不太清楚,你可以翻看我以 ...

  4. 转:云风skynet服务端框架研究

    转:  http://forthxu.com/blog/skynet.html skynet是云风编写的服务端底层管理框架,底层由C编写,配套lua作为脚本使用,可换python等其他脚本语言.sky ...

  5. 云风协程库coroutine源码分析

    前言 前段时间研读云风的coroutine库,为了加深印象,做个简单的笔记.不愧是大神,云风只用200行的C代码就实现了一个最简单的协程,代码风格精简,非常适合用来理解协程和用来提升编码能力. 协程简 ...

  6. 【Serverless】快速集成云函数HarmonyOS

    ​1.学习目标 什么是AppGallery Connect云函数 云函数是一项Serverless计算服务,提供FaaS(Function as a Service)能力,可以帮助开发者大幅简化应用开 ...

  7. 转:c的回归-云风

    C 的回归 周末出差,去另一个城市给公司的一个项目解决点问题.回程去机场的路上,我用手机上 google reader 打发时间.第一眼就看到孟岩大大新的一篇:Linux之父话糙理不糙 .主题是 C ...

  8. C 的 coroutine 库 via 云风的 BLOG

    今天实现了一个 C 用的 coroutine 库. 我相信这个东西已经被无数 C 程序员实现过了, 但是通过 google 找了许多, 或是接口不让我满意, 或是过于重量. 在 Windows 下, ...

  9. 云风的BLOG❳可靠 UDP 传输

    http://mp.weixin.qq.com/s?__biz=MzA3NjYxOTA0MQ==&mid=405432715&idx=1&sn=2e40ceafd4b298e1 ...

随机推荐

  1. sqlserver 常用函数(转)

    1.字符串函数 : len(expression) 返回给定字符串表达式的字符(而不是字节)个数,其中不包含尾随空格. datalength(Char_expr) 返回字符串包含字符数,但不包含后面的 ...

  2. SQL Server 权限的分类

    SQL Server 的权限可以分三类 第一类 server 层面上的: select * from sys.fn_builtin_permissions(default) where class_d ...

  3. SQL Server 查看数据页面

    第一步: 找到表的第一页dbcc ind(db_name,table_name,-1); 例子. dbcc ind(studio,person,-1);# pageFID  是文件号   pagePI ...

  4. Kill 正在执行的存储过程

    1.找到正在执行的存储过程的 sid ,serial# select   b.sid,b.SERIAL#,a.OBJECT, 'alter system kill session   ' || ''' ...

  5. java.sql.ResultSetMetaData.getColumnLabel和getColumnName的区别

    如果将ResultSet的结果映射到HashMap中,要使用getColumnLabel,而不要用getColumnName,这样可提高程序的健壮性 理由: getColumnName返回的是sql语 ...

  6. Qt编写端口扫描工具

    Qt提供了QTcpSocket类,可以方便地建立TCP连接.利用这一功能,Maxiee编写了一个简单地端口扫描工具. 软件的功能就是,扫描某一网段的固定端口,如80端口,若目的地址开放了这一端口,那么 ...

  7. 04737_C++程序设计_第8章_多态性和虚函数

    例8.1 分析下面程序的输出结果. 例8.2 分别使用指针和引用的display函数. #include <iostream> using namespace std; const dou ...

  8. 关于Lambda表达式访问外部变量

    在<C#高级编程>一书中提到通过Lambda表达式可以访问Lambda表达式块外部的变量 ,这是一个很好的功能(类似Js中的 闭包).但是如果没有正确的使用,会非常危险. 比如下面的事例中 ...

  9. iframe自适应高度代码

    var adjustIframe = function (id) { var iframe = document.getElementById(id) var idoc = iframe.conten ...

  10. 关于bootstrap弹出二级对话框的使用

    弹出二级对话框,即在对话框的基础上再弹出一个对话框.这对于CRM管理类系统来说应用场景很常见.看到网上有关于实现二级弹出框的方法,需要在一级对话框页面上添加不少css样式.其实,完全可以不用这么麻烦. ...