You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 06:12:09