1. 程式人生 > >【轉】 cocos2dx 3.x C++搭建protobuf環境

【轉】 cocos2dx 3.x C++搭建protobuf環境

person ccf binding csdn bind taf protoc -cp strlen

http://blog.csdn.net/ganpengjin1/article/details/50964961

Cocos2dx 裏面在網絡遊戲通信這一塊一般我們都會采用protobuf來進行通信,cocos引擎沒有集成C++的protobuf,那我們只能自己來集成了。因為protobuf有很多版本,那麽我們怎麽去下載與引擎中想對應的protobuf版本呢。

他在

[cpp] view plain copy
  1. cocos2d-x\tools\simulator\libsimulator\lib\protobuf-lite

在這裏目錄下面有個

config.h文件,在第一行就可以看到當前版本,那我們就去http://code.google.com/p/protobuf/downloads/list

下載版本。

第二,下載下來後,我們添加這個protobuf工程到你的項目工程中

第三,右擊你的項目,添加該protobuf為依賴項目,把cocos2d-x\tools\simulator\libsimulator\lib\protobuf-lite,這下面的google下面的protobuf文件夾全部刪掉,替換成你解壓後的src下面的google中的protobuf。config.h文件也替換成你的vsprojects下的config.h文件

第四,開始編譯--》應該是沒有問題的

第五,我們要開始生成我們的.proto文件了,怎麽弄呢?還記得先前下載下來的protobuf文件嗎?解壓後,裏面有個vsprojects 文件夾,protobuf.sln 用Vs打開這個工程編譯protobuf工程,編譯完之後,再編譯test工程,這個時候會生成protoc.exe文件,這個文件就是我們所需要的。

第六,我們開始編寫我們的proto文件了,寫一個.bat文件,內容:

[cpp] view plain copy
  1. protoc.exe MsgProtocol.proto --cpp_out=./
  2. pause


其中:***.proto為文件名, cpp為生成的C++文件,還可以生成其他:java, python等,但是暫時不支持lua的,out後面是路徑,跟你的.proto文件是同一路徑

.proto文件中的內容可以直接定義message,例如:

[cpp] view plain copy
  1. message Person {
  2. required int32 id = 1;
  3. required string name = 2;
  4. optional string emial = 3;
  5. optional string text = 4;
  6. enum MsgType {
  7. MsgType_None = 0;
  8. MsgType_ONE = 1;
  9. MsgType_TWO = 2;
  10. MsgType_THREE = 3;
  11. MsgType_FOUR = 4;
  12. MsgType_FIVE = 5;
  13. }
  14. enum MsgStatus {
  15. MsgStatus_NONE = 0;
  16. MsgStatus_ONE = 1;
  17. MsgStatus_TWO = 2;
  18. }
  19. optional MsgType msg = 5;
  20. optional MsgStatus status = 6;
  21. }


第七,寫完bat,proto後,把.bat, protoc.exe, .proto文件復制到你項目目錄下面(其實,任意位置都可以,只要這三個文件保持在同一目錄就可以),運行.bat文件後,會成成.pb.cc,.pb.h文件,這個就是你生成的文件,把這兩個文件復制到你的項目中,你就可以隨意使用了。

以上是C++集成protobuf。。

下面來講一下Lua集成Protobuf,先去下載pbc:https://github.com/cloudwu/pbc

把這個項目下來,添加到你的項目工程中,然後編譯一下。應該是編譯沒有問題的。接下來講重要的部分:

第一:右擊的項目工程,把pbc添加為依賴項

第二:在pbc工程裏面創建一個頭文件"pbc-lua.h"(最好放在工程的pbc目錄下),內容如下:

[cpp] view plain copy
  1. #ifndef PBC_LUA_H
  2. #define PBC_LUA_H
  3. //
  4. // pbc-lua.h
  5. // pbc
  6. //
  7. // Created by ArcherPeng on 15/7/21.
  8. // Copyright (c) 2015年 ztgame. All rights reserved.
  9. //
  10. #if defined(_USRDLL)
  11. #define LUA_EXTENSIONS_DLL __declspec(dllexport)
  12. #else /* use a DLL library */
  13. #define LUA_EXTENSIONS_DLL
  14. #endif
  15. #if __cplusplus
  16. extern "C" {
  17. #endif
  18. #include "lauxlib.h"
  19. int LUA_EXTENSIONS_DLL luaopen_protobuf_c(lua_State *L);
  20. #if __cplusplus
  21. }
  22. #endif
  23. #endif/* pbc_pbc_lua_h */


第三:把binding/lua/pbc-lua.c (也放在工程的pbc目錄下),代碼如下:

[cpp] view plain copy
  1. #ifdef __cplusplus
  2. extern "C" {
  3. #endif
  4. #include "lua.h"
  5. #include "lualib.h"
  6. #include "lauxlib.h"
  7. #include "pbc.h"
  8. #include "pbc-lua.h"//引入剛剛創建的頭文件
  9. #ifdef __cplusplus
  10. }
  11. #endif


第四:

首先要修改pbc工程的頭文件搜索路徑:

加入一條路徑:項目路徑/frameworks/cocos2d-x/external/lua/lua (這裏最好使用相對路徑,但絕對路徑也可以)

第五:

添加完成後,回到AppDelegate.cpp中,引入頭文件#include"pbc/pbc/pbc-lua.h",並在boolAppDelegate::applicationDidFinishLaunching()方法中加入luaopen_protobuf_c(L);用於將protobuf的函數註冊進LUA,代碼如下:

[cpp] view plain copy
  1. bool AppDelegate::applicationDidFinishLaunching()
  2. {
  3. // set default FPS
  4. Director::getInstance()->setAnimationInterval(1.0 / 60.0f);
  5. // register lua module
  6. auto engine = LuaEngine::getInstance();
  7. ScriptEngineManager::getInstance()->setScriptEngine(engine);
  8. lua_State* L = engine->getLuaStack()->getLuaState();
  9. lua_module_register(L);
  10. luaopen_protobuf_c(L);//在lua中註冊Proto函數
  11. register_all_packages();
  12. LuaStack* stack = engine->getLuaStack();
  13. stack->setXXTEAKeyAndSign("2dxLua", strlen("2dxLua"), "XXTEA", strlen("XXTEA"));
  14. if (engine->executeScriptFile("src/main.lua"))
  15. {
  16. return false;
  17. }
  18. return true;
  19. }

第六:接下來我們要再為LUA註冊一個函數用於讀取pb文件數據:

[cpp] view plain copy
  1. static int readProtobufFile(lua_State *L)
  2. {
  3. const char *buff = luaL_checkstring(L, -1);
  4. Data data = CCFileUtils::getInstance()->getDataFromFile(buff);
  5. lua_pushlstring(L, (const char*)data.getBytes(), data.getSize());
  6. return 1; /* number of results */
  7. }
並將該函數註冊到lua中,在staticint register_all_packages()中添加如下語句:
[cpp] view plain copy
  1. // If you want to use packages manager to install more packages,
  2. // don‘t modify or remove this function
  3. static int register_all_packages()
  4. {
  5. lua_State *L = LuaEngine::getInstance()->getLuaStack()->getLuaState();
  6. luaopen_protobuf_c(L);
  7. lua_register(L,"readProtobufFile",readProtobufFile);
  8. return 0; //flag for packages manager
  9. }

第七:編譯並運行,編譯通過後,遊戲運行成功!
第八:

至此,C++端設置完畢。但是並沒有結束,還有最後幾步。

回到遊戲項目的binding/lua目錄,找到"protobuf.lua"文件,將其復制到lua項目的src目錄下。


第九:

在LUA中Protobuf的簡單例程:

require "app/protobuf.lua" //導入你的protobuf.lua文件

[cpp] view plain copy
  1. local pbFilePath = cc.FileUtils:getInstance():fullPathForFilename("app/MsgProtocol.pb")
  2. release_print("PB file path: "..pbFilePath)
  3. local buffer = readProtobufFile(pbFilePath)
  4. protobuf.register(buffer) --註:protobuf 是因為在protobuf.lua裏面使用module(protobuf)來修改全局名字
  5. local stringbuffer = protobuf.encode("Person",
  6. {
  7. name = "Alice",
  8. id = 12345,
  9. phone = {
  10. {
  11. number = "87654321"
  12. },
  13. }
  14. })
  15. local slen = string.len(stringbuffer)
  16. local temp = ""
  17. for i=1, slen do
  18. temp = temp .. string.format("0xX, ", string.byte(stringbuffer, i))
  19. end
  20. release_print(temp)
  21. local result = protobuf.decode("Person", stringbuffer)
  22. release_print("result name: "..result.name)
  23. release_print("result name: "..result.id)

MsgProtocol.proto的內容:

[cpp] view plain copy
  1. message Person {
  2. required string name = 1;
  3. required int32 id = 2;
  4. optional string email = 3;
  5. enum PhoneType {
  6. MOBILE = 0;
  7. HOME = 1;
  8. WORK = 2;
  9. }
  10. message PhoneNumber {
  11. required string number = 1;
  12. optional PhoneType type = 2 [default = HOME];
  13. }
  14. repeated PhoneNumber phone = 4;
  15. }
  16. message AddressBook {
  17. repeated Person person = 1;
  18. }
需要生成.pb文件的話,你利用前面C++的集成方法生成:protoc.exe,.bat文件生成即可 註。這裏需要生成的是pb文件,所以.bat的內容需要修改一下: [cpp] view plain copy
  1. protoc.exe --descriptor_set_out=./MsgProtocol.pb ./MsgProtocol.proto
MsgProtocol 為你的pb文件名



最後添加到android.mk裏面,蛋疼啊。。。 其實很簡單的,只需要添加你的文件目錄即可,用*.cpp或者*.c來搜索,這樣實在是太方便了,省了很多事情,不再逐個逐個的添加(參考:http://blog.csdn.net/fu_zk/article/details/12836431)
[cpp] view plain copy
  1. LOCAL_PATH := $(call my-dir)
  2. include $(CLEAR_VARS)
  3. LOCAL_MODULE := cocos2dlua_shared
  4. LOCAL_MODULE_FILENAME := libcocos2dlua
  5. FILE_LIST := hellolua/main.cpp
  6. FILE_LIST += $(wildcard $(LOCAL_PATH)/../../Classes/*.cpp)
  7. FILE_LIST += $(wildcard $(LOCAL_PATH)/../../Classes/lua/*.cpp)
  8. FILE_LIST += $(wildcard $(LOCAL_PATH)/../../Classes/socket/*.cpp)
  9. FILE_LIST += $(wildcard $(LOCAL_PATH)/../../Classes/hotUpdate/*.cpp)
  10. FILE_LIST += $(wildcard $(LOCAL_PATH)/../../Classes/ide-support/*.cpp)
  11. FILE_LIST += $(wildcard $(LOCAL_PATH)/../../Classes/ide-support/*.c)
  12. #添加
  13. FILE_LIST += $(wildcard $(LOCAL_PATH)/../../Classes/pbc/binding/lua/*.c)
  14. FILE_LIST += $(wildcard $(LOCAL_PATH)/../../Classes/pbc/src/*.c)
  15. LOCAL_SRC_FILES := $(FILE_LIST:$(LOCAL_PATH)/%=%)
  16. #你的工程目錄
  17. LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../Classes
  18. #你的工程目錄其他自文件夾目錄
  19. LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../Classes/pbc
  20. LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../Classes/pbc/src
  21. # _COCOS_HEADER_ANDROID_BEGIN
  22. # _COCOS_HEADER_ANDROID_END
  23. LOCAL_STATIC_LIBRARIES := cocos2d_lua_static
  24. LOCAL_STATIC_LIBRARIES += cocos2d_simulator_static
  25. # _COCOS_LIB_ANDROID_BEGIN
  26. # _COCOS_LIB_ANDROID_END
  27. include $(BUILD_SHARED_LIBRARY)
  28. $(call import-module,scripting/lua-bindings/proj.android)
  29. $(call import-module,tools/simulator/libsimulator/proj.android)
  30. # _COCOS_LIB_IMPORT_ANDROID_BEGIN
  31. # _COCOS_LIB_IMPORT_ANDROID_END


【轉】 cocos2dx 3.x C++搭建protobuf環境