protocol buffer从3.0 原生的compiler支持c++,Java,Python,Go,Ruby,JavaNano,JavaScript,Objective-C,C#,PHP这篇文章作为上一篇文章的补充,简单记录下一些变化。
protobuf的开源地址为:https://github.com/google/protobuf
protocol compiler下载地址为:https://github.com/google/protobuf/releases
官方定义message类型的例子:
syntax="proto3"
message SearchRequest{
string query=1;
int32 page_number=2;
int32 result_per_page=3;
}
..proto文件的第一行指定使用proto3的语法。
特定语言的声明使用option关键定和选项名
option java_package="com.example.tutorial";//定义生成的java包
option java_outer_classname="AddressBookProtos";//定义java类名
option csharp_namespace="Google.Protobuf.Examples.AddressBook";//定义c#的命名空间
变化
1.字段前取消了required和optional两个关键字,目前可用的只有repeated关键字。
2.不可以现设置默认值了。
a.string默认为空串
b.枚举默认为第一个枚举定义的第一个值。并且必须是0
c.bytes默认为空bytes
d.bool默认为false
e.数字类型默认为0
3.类型对应表
.proto Type | Notes | C++ Type | Java Type | Python Type[2] | Go Type | Ruby Type | C# Type | PHP Type |
---|---|---|---|---|---|---|---|---|
double | double | double | float | float64 | Float | double | float | |
float | float | float | float | float32 | Float | float | float | |
int32 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead. | int32 | int | int | int32 | Fixnum or Bignum (as required) | int | integer |
int64 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead. | int64 | long | int/long[3] | int64 | Bignum | long | integer/string[5] |
uint32 | Uses variable-length encoding. | uint32 | int[1] | int/long[3] | uint32 | Fixnum or Bignum (as required) | uint | integer |
uint64 | Uses variable-length encoding. | uint64 | long[1] | int/long[3] | uint64 | Bignum | ulong | integer/string[5] |
sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int | int | int32 | Fixnum or Bignum (as required) | int | integer |
sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long | int/long[3] | int64 | Bignum | long | integer/string[5] |
fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 228. | uint32 | int[1] | int | uint32 | Fixnum or Bignum (as required) | uint | integer |
fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 256. | uint64 | long[1] | int/long[3] | uint64 | Bignum | ulong | integer/string[5] |
sfixed32 | Always four bytes. | int32 | int | int | int32 | Fixnum or Bignum (as required) | int | integer |
sfixed64 | Always eight bytes. | int64 | long | int/long[3] | int64 | Bignum | long | integer/string[5] |
bool | bool | boolean | bool | bool | TrueClass/FalseClass | bool | boolean | |
string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode[4] | string | String (UTF-8) | string | string |
bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str | []byte | String (ASCII-8BIT) | ByteString | string |
proto代码编译
语法:
protoc --proto_path=IMPORT_PATH --cpp_out=DST_DIR --java_out=DST_DIR --python_out=DST_DIR --go_out=DST_DIR --ruby_out=DST_DIR --javanano_out=DST_DIR --objc_out=DST_DIR --csharp_out=DST_DIR path/to/file.proto
--proto_path 当proto文件中使用import时指定的导入文件的位置
--cpp_out c++输出目录
--java_out java输出目录
--python_out
--go_out
--ruby_out ruby输出目录
--objc_out oc输出目录
--csharp_out c#输出目录
path/to/file.proto为要编译的proto文件
使用
proto内容:
syntax="proto3";
option java_package="com.ztimage";
option java_outer_classname="WebUI";
option csharp_namespace="ZTImage.WebUI";
message SearchRequest{
string query=1;
int32 page_number=2;
int32 result_per_page=3;
}
执行命令:protoc --csharp_out d:/programs/protoc/bin WebUI.proto
生成代码:
// Generated by the protocol buffer compiler. DO NOT EDIT! // source: WebUI.proto #pragma warning disable 1591, 0612, 3021 #region Designer generated code using pb = global::Google.Protobuf; using pbc = global::Google.Protobuf.Collections; using pbr = global::Google.Protobuf.Reflection; using scg = global::System.Collections.Generic; namespace ZTImage.WebUI { /// <summary>Holder for reflection information generated from WebUI.proto</summary> public static partial class WebUIReflection { #region Descriptor /// <summary>File descriptor for WebUI.proto</summary> public static pbr::FileDescriptor Descriptor { get { return descriptor; } } private static pbr::FileDescriptor descriptor; static WebUIReflection() { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "CgtXZWJVSS5wcm90byJMCg1TZWFyY2hSZXF1ZXN0Eg0KBXF1ZXJ5GAEgASgJ", "EhMKC3BhZ2VfbnVtYmVyGAIgASgFEhcKD3Jlc3VsdF9wZXJfcGFnZRgDIAEo", "BUIkCgtjb20uenRpbWFnZUIFV2ViVUmqAg1aVEltYWdlLldlYlVJYgZwcm90", "bzM=")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::ZTImage.WebUI.SearchRequest), global::ZTImage.WebUI.SearchRequest.Parser, new[]{ "Query", "PageNumber", "ResultPerPage" }, null, null, null) })); } #endregion } #region Messages public sealed partial class SearchRequest : pb::IMessage<SearchRequest> { private static readonly pb::MessageParser<SearchRequest> _parser = new pb::MessageParser<SearchRequest>(() => new SearchRequest()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser<SearchRequest> Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::ZTImage.WebUI.WebUIReflection.Descriptor.MessageTypes[0]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public SearchRequest() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public SearchRequest(SearchRequest other) : this() { query_ = other.query_; pageNumber_ = other.pageNumber_; resultPerPage_ = other.resultPerPage_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public SearchRequest Clone() { return new SearchRequest(this); } /// <summary>Field number for the "query" field.</summary> public const int QueryFieldNumber = 1; private string query_ = ""; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string Query { get { return query_; } set { query_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// <summary>Field number for the "page_number" field.</summary> public const int PageNumberFieldNumber = 2; private int pageNumber_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int PageNumber { get { return pageNumber_; } set { pageNumber_ = value; } } /// <summary>Field number for the "result_per_page" field.</summary> public const int ResultPerPageFieldNumber = 3; private int resultPerPage_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int ResultPerPage { get { return resultPerPage_; } set { resultPerPage_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as SearchRequest); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(SearchRequest other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (Query != other.Query) return false; if (PageNumber != other.PageNumber) return false; if (ResultPerPage != other.ResultPerPage) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (Query.Length != 0) hash ^= Query.GetHashCode(); if (PageNumber != 0) hash ^= PageNumber.GetHashCode(); if (ResultPerPage != 0) hash ^= ResultPerPage.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (Query.Length != 0) { output.WriteRawTag(10); output.WriteString(Query); } if (PageNumber != 0) { output.WriteRawTag(16); output.WriteInt32(PageNumber); } if (ResultPerPage != 0) { output.WriteRawTag(24); output.WriteInt32(ResultPerPage); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (Query.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(Query); } if (PageNumber != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(PageNumber); } if (ResultPerPage != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(ResultPerPage); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(SearchRequest other) { if (other == null) { return; } if (other.Query.Length != 0) { Query = other.Query; } if (other.PageNumber != 0) { PageNumber = other.PageNumber; } if (other.ResultPerPage != 0) { ResultPerPage = other.ResultPerPage; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 10: { Query = input.ReadString(); break; } case 16: { PageNumber = input.ReadInt32(); break; } case 24: { ResultPerPage = input.ReadInt32(); break; } } } } } #endregion } #endregion Designer generated code
在项目中引用Google.Protobuf程序集,生成的代码放到项目中
测试代码:
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using Google.Protobuf; namespace ZTImage.WebUI { class Program { static void Main(string[] args) { SearchRequest request = new SearchRequest() { Query="age>0 and age <18", PageNumber=1, ResultPerPage=50 }; using (var output = File.Create("mr.dat")) { request.WriteTo(output); } SearchRequest sr = null; using (var input = File.OpenRead("mr.dat")) { sr = SearchRequest.Parser.ParseFrom(input); } Console.WriteLine("Query:{0},PageNumber:{1},ResultPerPage:{2}",sr.Query,sr.PageNumber,sr.ResultPerPage); Console.ReadKey(); } } }
结果:
Query:age>0 and age <18,PageNumber:1,ResultPerPage:50
pref:
500W writer 2022ms read 1864ms