能否用protobuf-net生成可用于C++代码生成的.proto文件?
需求实现可行性说明
你的需求可以通过protobuf-net实现,但需要对C#类做适配性修改(添加protobuf-net的序列化标记),同时处理Protobuf原生不支持继承的特性适配,以下是具体步骤和说明:
1. 适配C#类的protobuf-net标记
Protobuf-net依赖属性标记识别可序列化的类型和字段,同时因Protobuf原生不支持类继承,需用[ProtoInclude]声明基类与派生类的关联:
修改后的C#代码(修正原代码拼写错误+添加序列化标记):
using ProtoBuf; [ProtoContract] public class Point { [ProtoMember(1)] public double x; [ProtoMember(2)] public double y; } [ProtoContract] [ProtoInclude(101, typeof(Square))] // 标记派生类Square,字段ID需唯一且不与基类字段冲突 [ProtoInclude(102, typeof(Triangle))] // 标记派生类Triangle public abstract class Polygon { [ProtoMember(1)] public List<Point> Vertices; public Polygon() { Vertices = new(); } public override string ToString() { string ans = ""; foreach (var point in Vertices) { ans += $"({point.x},{point.y})"; } return ans; } } [ProtoContract] public class Square : Polygon { public Square(Point a, Point b, Point c, Point d) { Vertices.Add(a); Vertices.Add(b); Vertices.Add(c); Vertices.Add(d); } } [ProtoContract] public class Triangle : Polygon { public Triangle(Point a, Point b, Point c) { Vertices.Add(a); Vertices.Add(b); Vertices.Add(c); } }
2. 生成Proto3格式的.proto文件
protobuf-net支持生成Proto3语法的.proto文件,可通过代码调用Serializer.GetProto<T>()方法生成:
var protoContent = Serializer.GetProto<Polygon>(ProtoSyntax.Proto3); File.WriteAllText("shapes.proto", protoContent);
生成的shapes.proto大致如下:
syntax = "proto3"; message Point { double x = 1; double y = 2; } message Polygon { repeated Point Vertices = 1; oneof kind { Square Square = 101; Triangle Triangle = 102; } } message Square { } message Triangle { }
注:示例中Square和Triangle无额外字段,因此生成的消息体为空,仅作类型标识;若派生类有自定义字段,会自动追加到对应消息中。
3. 用官方protoc编译生成C++类
拿到生成的.proto文件后,直接使用Google官方protoc编译器编译生成C++代码:
protoc --cpp_out=. shapes.proto
编译后会生成shapes.pb.h和shapes.pb.cc文件,包含对应的C++类定义。
4. 确保C#与C++的消息互通一致性
- C#侧:protobuf-net序列化/反序列化
Polygon及其派生类时,会自动处理类型标识,对应到Proto中的oneof字段 - C++侧:需通过
Polygon的kind()方法判断具体类型,再获取对应派生类实例,保证反序列化后的数据与C#侧完全一致
关键注意事项
[ProtoMember]中的字段ID必须在整个消息体系中唯一,且C#代码与生成的Proto文件需完全对应- 若不需要强制Proto3,可省略
ProtoSyntax.Proto3参数,默认生成Proto2格式 - 原代码中的拼写错误(
Vertecies→Vertices、Sqare→Square)必须修正,否则会导致序列化失败
内容的提问来源于stack exchange,提问作者Curtwagner1984
相关产品推荐
相关产品推荐

