keywords: [UE4]Android NDK打包版本执行protobuf的ParseFromArray函数崩溃

keywords:UE4、protobuf-lite、Android NDK、ParseFromArray、Crash

protobuf与android ndk编译后,集成到UE4中执行时,每当执行ParseFromArray时就会崩溃(Windows版本没有问题):

MessageTest msg;
bool rs = msg.ParseFromArray(buffer, buffer_size);

解决办法:将ParseFromArray()函数内部的代码复制出来,放在工程的代码中,然后再执行。

protobuf 2.x

#ifndef    __ProtobufHelper_H__
#define    __ProtobufHelper_H__

#include <google/protobuf/message_lite.h>
#include <google/protobuf/io/coded_stream.h>

class ProtobufHelper
{
public:

    static bool Parse(::google::protobuf::MessageLite& Message, const char* Data, int Size)
    {
        ::google::protobuf::io::CodedInputStream input(reinterpret_cast<const uint8*>(Data), Size);

        return Message.MergePartialFromCodedStream(&input) && input.ConsumedEntireMessage();
    }
};

#endif

protobuf 3.x

#ifndef    __ProtobufHelper_H__
#define    __ProtobufHelper_H__

#include <google/protobuf/message_lite.h>
#include <google/protobuf/io/coded_stream.h>
#include "CoreMinimal.h"

class ProtobufHelper
{
public:

    static bool Parse(::google::protobuf::MessageLite& Message, const void* Data, int Size)
    {
        ::google::protobuf::io::CodedInputStream input(static_cast<const uint8*>(Data), Size);

        Message.Clear();

        if (!Message.MergePartialFromCodedStream(&input))
        {
            return false;
        }
        
        if (!Message.IsInitialized()) 
        {
            //GOOGLE_LOG(ERROR) << InitializationErrorMessage("parse", *message);
            UE_LOG(LogTemp, Error, TEXT("protobuf message isn't initialized."));
            return false;
        }
        return true;
    }
};

#endif

使用示例

MessageTest msg;
bool rs = ProtobufHelper::Parse(msg, buffer, buffer_size);

message嵌套问题

protobuf 3.x版本,如果在一个模版文件中定义多个message,即使用上面的Parse函数,UE4打包Android版本运行时也会导致崩溃。2.x版本正常

SearchResponse.proto

syntax = "proto3";

option optimize_for = LITE_RUNTIME;

message SearchResponse {
  repeated Result results = 1;
}

message Result {
  string url = 1;
  string title = 2;
  repeated string snippets = 3;
}

解决办法:一个proto文件只定义一种message,通过import方式导入。

SearchResponse.proto

syntax = "proto3";

option optimize_for = LITE_RUNTIME;

import "Result.proto";

message SearchResponse {
  repeated Result results = 1;
}

Result.proto

syntax = "proto3";

option optimize_for = LITE_RUNTIME;

message Result {
  string url = 1;
  string title = 2;
  repeated string snippets = 3;
}

当才华无法撑起野心时,应静下心学习。