ocos2dx-lua采用pbc解析protobuf 不支持message嵌套和枚举不支持整数的处理方法

  • PBC不支持嵌套message的解析


在cocos2dx-lua中应用pbc解析protobuf协议格式发现,其对嵌套消息的解析很不友好。 经过for pairs循环检验发现,decode方法并没有解析内部嵌套的子消息。


进一步检查发现,子消息的输出格式为table:第一个字段为子消息的名字, 第2个字段为一个奇怪的字符串(一般为子消息的第一个字段)。进行了各种尝试,发现只要访问一次子消息实际存在的字段,则子消息的结构自动输出为正常。


很奇怪吧!大神的代码总是用各种元表奇奇怪怪的实现来追求效率, 而实际游戏开发中总是需要各种通用的写法。


如果不能对字段进行打印调试毫无疑问是没办法正常开发的,最后发现只要针对子消息结构调用一次decode则可以解决嵌套消息无法正常输出的问题。需要编写下面代码

修改:protpbuf.lua

增加以下方法

function decodeAll(typename, buffer)
   local ret = decode(typename, buffer, length)
   if ret then
      decodeTable(ret)
   end
   return ret
end
 
function decodeTable(tbl)
   for k,v in pairs(tbl) do
       if type(v) == "table" then
          --这里的xxxx请自行替换成protobuf的package
          if(type(v[1]) == "string" and string.find(v[1],"XXXXX.")) then
               local ret = decode(v[1], v[2])
               if ret then
                  tbl[k] = ret
               end
          end
          decodeTable(tbl[k])
       end
   end
end


  游戏中调用protobuf.decodeAll即可正常解析了


另外发现decode后的lua table在访问不存在的字段会报assert, 修改下面这个方法可以解决这个问题

function _decode_type_meta:__index(key)
    local t, msg = c._env_type(P, self._CType, key)
    --local func = assert(_reader[t], key)(msg)
    local reader = _reader[t]
    local func
    if reader then
        func = reader(msg)
    else
        func = function() end
    end
    self[key] = func
    return func
end

这样我们就可以在游戏中比较友好的使用pbc来解析proto格式了


  • PBC中枚举不支持整数解决方案

再就是pbc默认将枚举解析成字符串,这使用起来有不是很方便,修改如下:

static void
push_value(lua_State *L, int type, const char * type_name, union pbc_value *v) {
	switch(type) {
	case PBC_INT:
		lua_pushinteger(L, (int)v->i.low);
		break;
	case PBC_REAL:
		lua_pushnumber(L, v->f);
		break;
	case PBC_BOOL:
		lua_pushboolean(L, v->i.low);
		break;
	case PBC_ENUM:
		//lua_pushstring(L, v->e.name); // 支持整数
		lua_pushinteger(L, v->e.id);
		break;
		
		...
	}

还要修改protpbuf.lua,如下:

解析pb时使用

_reader[1] = function(msg) return _reader.int end
_reader[2] = function(msg) return _reader.real end
_reader[3] = function(msg) return _reader.bool end
--_reader[4] = function(msg) return _reader.string end
_reader[4] = function(msg) return _reader.int end
_reader[5] = function(msg) return _reader.string end
_reader[6] = function(msg)
	local message = _reader.message
	return	function(self,key)
			return message(self, key, msg)
		end
end

序列化pb时使用

_writer[1] = function(msg) return _writer.int end
_writer[2] = function(msg) return _writer.real end
_writer[3] = function(msg) return _writer.bool end
--_writer[4] = function(msg) return _writer.string end
_writer[4] = function(msg) return _writer.int end
_writer[5] = function(msg) return _writer.string end
_writer[6] = function(msg)
	local message = _writer.message
	return	function(self,key , v)
			return message(self, key, v, msg)
		end
end

这样枚举就可以支持整数了

但是proto文件定义的枚举值,在lua还是不能直接使用,需要在lua重新定义下,这个有谁找到了解决办法,求告之!


你可能感兴趣的:(Cocos2d-x)