У меня есть файл .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. Как правильно прочитать файл, чтобы его можно было десериализовать?
Для этого должно быть достаточно:
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");
}
}
Модель, которую вы показываете, представляет собой для protobuf-net, необязательный поля (несколько с нулевым значением по умолчанию). Следовательно, любые нули могут быть опущены, что приведет к тому, что читатель c ++ отклонит сообщение (поскольку ваш .proto перечисляет его по мере необходимости).
Чтобы получить представителя .proto:
string proto = Serializer.GetProto<YourType>();
Или сделать их «обязательными» в c #:
[ProtoMember(3, IsRequired = true)]
(так далее)