Protobuf.NET使用

时间:2011-07-21 05:00:53

标签: c# c++ serialization protobuf-net

需要在托管c#和非托管c ++之间发送一些数据。经过一番研究 我试着使用Protobuf.NET。

我不确定我是否理解ProtoBuf的功能...

  1. 在Proto中构建一个类型定义。我在项目c ++和c#
  2. 中都需要这种类型定义
  3. 使用命令行工具“protogen.exe”从类型定义中获取.cs文件和.cpp,.h
  4. 将.cs文件复制到我的c#项目和我的c ++解决方案中的.cpp,.h。
  5. 似乎我很愚蠢地解决这个问题。这是我的问题和疑问。

    1. 是否可以在c#中定义类型以生成c ++中的文件?
    2. 尝试使用带有以下文件的命令行工具protogen.exe

    3. test1.proto

      using ProtoBuf;
      namespace ProtocolBuffers
      {
          [ProtoContract]
          class Person
          {
              [ProtoMember(1)]
              public int Id {get;set;}
              [ProtoMember(2)]
              public string Name { get; set; }
          }
      }
      

      test2.proto

      message Person {
        required int32 id = 1;
        required string name = 2;
        optional string email = 3;
      }
      

      没有什么对我有用。真的尝试了一切。我把原型文件放入了 命令行目录,尝试了每个选项来设置目录。如何轻松构建它们? 第二个文件正在使用c ++的标准proto命令行工具,但我也需要它用于c#。真的需要你的帮助。

3 个答案:

答案 0 :(得分:4)

首先,请注意protobuf-net只是一个可用的.NET实现;反正...

“test1.proto”不是.proto - 它是C#;一个.proto不是必需的用于protobuf-net,但在你的互操作场景中,这是一个非常好的主意。有VS2010插件,或者是protobuf-net zip中的protogen工具:

 protogen -i:test2.proto -o:test2.cs

这应该生成test2.cs内容:

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

// Generated from: test2.proto
namespace test2
{
  [global::System.Serializable, global::ProtoBuf.ProtoContract(Name=@"Person")]
  public partial class Person : global::ProtoBuf.IExtensible
  {
    public Person() {}

    private int _id;
    [global::ProtoBuf.ProtoMember(1, IsRequired = true, Name=@"id", DataFormat = global::ProtoBuf.DataFormat.TwosComplement)]
    public int id
    {
      get { return _id; }
      set { _id = value; }
    }
    private string _name;
    [global::ProtoBuf.ProtoMember(2, IsRequired = true, Name=@"name", DataFormat = global::ProtoBuf.DataFormat.Default)]
    public string name
    {
      get { return _name; }
      set { _name = value; }
    }

    private string _email = "";
    [global::ProtoBuf.ProtoMember(3, IsRequired = false, Name=@"email", DataFormat = global::ProtoBuf.DataFormat.Default)]
    [global::System.ComponentModel.DefaultValue("")]
    public string email
    {
      get { return _email; }
      set { _email = value; }
    }
    private global::ProtoBuf.IExtension extensionObject;
    global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing)
      { return global::ProtoBuf.Extensible.GetExtensionObject(ref extensionObject, createIfMissing); }
  }

}

请注意,如果您需要其他开关,例如,它可以尝试进行大小写规范化(因此您可以获得IdNameEmail等),或者希望它包括其他序列化程序支持(BinaryFormatterDataContractSerializer等)

答案 1 :(得分:2)

test1.proto不是有效的.proto文件。

test2.proto看起来很不错。请注意,您需要主protobuf项目中的编译器以生成C ++代码,并且需要来自protobuf-net的编译器以生成C#代码。我想你的大多数问题都来自于没有意识到你需要两个不同的编译器(但是你将两个相同的.proto文件都提供给了)。

答案 2 :(得分:0)

虽然我对ProtoBuf了解不多,但我知道有一种更简单的方法可以做到这一点。如果上面的类表示您尝试发送到C ++的数据,只需使用Serialization并序列化您的类,然后您可以将类和数据输出到XML文件。然后,您可以使用XmlLite或其他一些XML阅读器来读取您的类和数据。您甚至可以使用Boost来读取序列化类。