Cocos2dx 里面在网络游戏通信这一块一般我们都会采用protobuf来进行通信,cocos引擎没有集成C++的protobuf,那我们只能自己来集成了。因为protobuf有很多版本,那么我们怎么去下载与引擎中想对应的protobuf版本呢。
他在
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文件,内容:
protoc.exe MsgProtocol.proto --cpp_out=./
pause
其中:***.proto为文件名, cpp为生成的C++文件,还可以生成其他:java, python等,但是暂时不支持lua的,out后面是路径,跟你的.proto文件是同一路径
.proto文件中的内容可以直接定义message,例如:
message Person {
required int32 id = 1;
required string name = 2;
optional string emial = 3;
optional string text = 4;
enum MsgType {
MsgType_None = 0;
MsgType_ONE = 1;
MsgType_TWO = 2;
MsgType_THREE = 3;
MsgType_FOUR = 4;
MsgType_FIVE = 5;
}
enum MsgStatus {
MsgStatus_NONE = 0;
MsgStatus_ONE = 1;
MsgStatus_TWO = 2;
}
optional MsgType msg = 5;
optional MsgStatus status = 6;
}
第七,写完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目录下),内容如下:
#ifndef PBC_LUA_H
#define PBC_LUA_H
//
// pbc-lua.h
// pbc
//
// Created by ArcherPeng on 15/7/21.
// Copyright (c) 2015年 ztgame. All rights reserved.
//
#if defined(_USRDLL)
#define LUA_EXTENSIONS_DLL __declspec(dllexport)
#else /* use a DLL library */
#define LUA_EXTENSIONS_DLL
#endif
#if __cplusplus
extern "C" {
#endif
#include "lauxlib.h"
int LUA_EXTENSIONS_DLL luaopen_protobuf_c(lua_State *L);
#if __cplusplus
}
#endif
#endif/* pbc_pbc_lua_h */
第三:把
binding/lua/pbc-lua.c (也放在工程的pbc目录下),代码如下:
#ifdef __cplusplus
extern "C" {
#endif
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
#include "pbc.h"
#include "pbc-lua.h"//引入刚刚创建的头文件
#ifdef __cplusplus
}
#endif
第四:
首先要修改pbc工程的头文件搜索路径:
加入一条路径:项目路径/frameworks/cocos2d-x/external/lua/lua (这里最好使用相对路径,但绝对路径也可以)
第五:
添加完成后,回到AppDelegate.cpp中,引入头文件#include"pbc/pbc/pbc-lua.h",并在boolAppDelegate::applicationDidFinishLaunching()方法中加入luaopen_protobuf_c(L);用于将protobuf的函数注册进LUA,代码如下:
bool AppDelegate::applicationDidFinishLaunching()
{
// set default FPS
Director::getInstance()->setAnimationInterval(1.0 / 60.0f);
// register lua module
auto engine = LuaEngine::getInstance();
ScriptEngineManager::getInstance()->setScriptEngine(engine);
lua_State* L = engine->getLuaStack()->getLuaState();
lua_module_register(L);
luaopen_protobuf_c(L);//在lua中注册Proto函数
register_all_packages();
LuaStack* stack = engine->getLuaStack();
stack->setXXTEAKeyAndSign("2dxLua", strlen("2dxLua"), "XXTEA", strlen("XXTEA"));
if (engine->executeScriptFile("src/main.lua"))
{
return false;
}
return true;
}
接下来我们要再为LUA注册一个函数用于读取pb文件数据:
static int readProtobufFile(lua_State *L)
{
const char *buff = luaL_checkstring(L, -1);
Data data = CCFileUtils::getInstance()->getDataFromFile(buff);
lua_pushlstring(L, (const char*)data.getBytes(), data.getSize());
return 1; /* number of results */
}
并将该函数注册到lua中,在staticint register_all_packages()中添加如下语句:
// If you want to use packages manager to install more packages,
// don't modify or remove this function
static int register_all_packages()
{
lua_State *L = LuaEngine::getInstance()->getLuaStack()->getLuaState();
luaopen_protobuf_c(L);
lua_register(L,"readProtobufFile",readProtobufFile);
return 0; //flag for packages manager
}
第七:
编译并运行,编译通过后,游戏运行成功!
第八:
至此,C++端设置完毕。但是并没有结束,还有最后几步。
回到游戏项目的binding/lua目录,找到"protobuf.lua"文件,将其复制到lua项目的src目录下。
第九:
在LUA中Protobuf的简单例程:
require "app/protobuf.lua" //导入你的protobuf.lua文件
local pbFilePath = cc.FileUtils:getInstance():fullPathForFilename("app/MsgProtocol.pb")
release_print("PB file path: "..pbFilePath)
local buffer = readProtobufFile(pbFilePath)
protobuf.register(buffer) --注:protobuf 是因为在protobuf.lua里面使用module(protobuf)来修改全局名字
local stringbuffer = protobuf.encode("Person",
{
name = "Alice",
id = 12345,
phone = {
{
number = "87654321"
},
}
})
local slen = string.len(stringbuffer)
local temp = ""
for i=1, slen do
temp = temp .. string.format("0xX, ", string.byte(stringbuffer, i))
end
release_print(temp)
local result = protobuf.decode("Person", stringbuffer)
release_print("result name: "..result.name)
release_print("result name: "..result.id)
MsgProtocol.proto的内容:
message Person {
required string name = 1;
required int32 id = 2;
optional string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
required string number = 1;
optional PhoneType type = 2 [default = HOME];
}
repeated PhoneNumber phone = 4;
}
message AddressBook {
repeated Person person = 1;
}
需要生成.pb文件的话,你利用前面C++的集成方法生成:
protoc.exe,.bat文件生成即可
注。这里需要生成的是pb文件,所以.bat的内容需要修改一下:
protoc.exe --descriptor_set_out=./MsgProtocol.pb ./MsgProtocol.proto
MsgProtocol 为你的pb文件名
最后添加到android.mk里面,蛋疼啊。。。
其实很简单的,只需要添加你的文件目录即可,用*.cpp或者*.c来搜索,这样实在是太方便了,省了很多事情,不再逐个逐个的添加(参考:)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := cocos2dlua_shared
LOCAL_MODULE_FILENAME := libcocos2dlua
FILE_LIST := hellolua/main.cpp
FILE_LIST += $(wildcard $(LOCAL_PATH)/../../Classes/*.cpp)
FILE_LIST += $(wildcard $(LOCAL_PATH)/../../Classes/lua/*.cpp)
FILE_LIST += $(wildcard $(LOCAL_PATH)/../../Classes/socket/*.cpp)
FILE_LIST += $(wildcard $(LOCAL_PATH)/../../Classes/hotUpdate/*.cpp)
FILE_LIST += $(wildcard $(LOCAL_PATH)/../../Classes/ide-support/*.cpp)
FILE_LIST += $(wildcard $(LOCAL_PATH)/../../Classes/ide-support/*.c)
#添加
FILE_LIST += $(wildcard $(LOCAL_PATH)/../../Classes/pbc/binding/lua/*.c)
FILE_LIST += $(wildcard $(LOCAL_PATH)/../../Classes/pbc/src/*.c)
LOCAL_SRC_FILES := $(FILE_LIST:$(LOCAL_PATH)/%=%)
#你的工程目录
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../Classes
#你的工程目录其他自文件夹目录
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../Classes/pbc
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../Classes/pbc/src
# _COCOS_HEADER_ANDROID_BEGIN
# _COCOS_HEADER_ANDROID_END
LOCAL_STATIC_LIBRARIES := cocos2d_lua_static
LOCAL_STATIC_LIBRARIES += cocos2d_simulator_static
# _COCOS_LIB_ANDROID_BEGIN
# _COCOS_LIB_ANDROID_END
include $(BUILD_SHARED_LIBRARY)
$(call import-module,scripting/lua-bindings/proj.android)
$(call import-module,tools/simulator/libsimulator/proj.android)
# _COCOS_LIB_IMPORT_ANDROID_BEGIN
# _COCOS_LIB_IMPORT_ANDROID_END