Как прочитать двоичный файл .proto в C ++?

У меня есть файл .bin, созданный с использованием C # с библиотекой protobuf и следующим классом:

[ProtoContract]
class TextureAtlasEntry
{
[ProtoMember(1)]
public int Height { get; set; }

[ProtoMember(2)]
public string Name { get; set; }

[ProtoMember(3)]
public int Width { get; set; }

[ProtoMember(4)]
public int X { get; set; }

[ProtoMember(5)]
public int Y { get; set; }
}

Связанный файл .proto выглядит так

package TextureAtlasSettings;           // Namespace equivalent

message TextureAtlasEntry
{
required int32 Height = 1;
required string Name = 2;
required int32 Width = 3;
required int32 X = 4;
required int32 Y = 5;
}

Который был проанализирован через protoc.exe для создания TextureAtlasSettings.pb.cc и TextureAtlasSettings.pb.h. для C ++.

Я хотел бы прочитать результирующий двоичный файл в C ++, поэтому я попробовал следующий код

TextureAtlasSettings::TextureAtlasEntry taSettings;

ifstream::pos_type size;
char *memblock;

ifstream file("Content\\Protobuf\\TextureAtlas0.bin", ios::in | ios::binary);

if (file.is_open())
{
size = file.tellg();
memblock = new char[size];
file.seekg(0, ios::beg);
file.read(memblock, size);
file.close();

fstream input(&memblock[0], ios::in | ios::binary);

if (!taSettings.ParseFromIstream(&file))
{
printf("Failed to parse TextureAtlasEntry");
}

delete[] memblock;
}

Код выше всегда будет вызывать printf. Как правильно прочитать файл, чтобы его можно было десериализовать?

1

Решение

Для этого должно быть достаточно:

TextureAtlasSettings::TextureAtlasEntry taSettings;

ifstream file("Content\\Protobuf\\TextureAtlas0.bin", ios::in | ios::binary);

if (file.is_open())
{
if (!taSettings.ParseFromIstream(&file))
{
printf("Failed to parse TextureAtlasEntry");
}
}
1

Другие решения

Модель, которую вы показываете, представляет собой для protobuf-net, необязательный поля (несколько с нулевым значением по умолчанию). Следовательно, любые нули могут быть опущены, что приведет к тому, что читатель c ++ отклонит сообщение (поскольку ваш .proto перечисляет его по мере необходимости).

Чтобы получить представителя .proto:

string proto = Serializer.GetProto<YourType>();

Или сделать их «обязательными» в c #:

[ProtoMember(3, IsRequired = true)]

(так далее)

3

По вопросам рекламы [email protected]