2

We use protocol buffers for communication between native C++ apps, but also between native C++ app and .NET application (all is VS2012) via protobuf-net r666. We rely in C++ heavily on the has_ functions that are available for an optional element.

E.g. if we have a message with a field optional bool, it can be that it is not set, it is set to true, or it is set to false.

In C++ this can be checked with the function has_field and if set then the content can be fetched with get_field function. If not set, and get_field is called, then the get returns the default, which if not explicitly set is false (for a boolean).

This works perfectly in C++, but, in protobuf-net however, we cannot seem to find the equivalent of the has_ function, and, when the message is received, the field is added to the message and it's content is set to the default, being false. It's not a disaster that the field is there with the default, but the problem is that there is no has_ function to check whether it was set in the message.

Please advise whether this is a bug or whether we missed something in protobuf-net and that this actually is possible

Thx in advance. Wim

Wim Van Houts
  • 516
  • 1
  • 8
  • 16

1 Answers1

5

(I know we already covered this in the issue tracker - this is purely for visibility etc)

This relates to generating classes from .proto files, which in the case of protobuf-net is via the protogen tool. By default, it does not create the equivalent of has_* methods, but this can be enabled with the -p:detectMissing switch - which causes it to create *Specified accessors. The naming here is a .NET idiom, with *Specified recognised by some other .NET serializers and internal code. It also generates a private ShouldSerialize* method, which again helps some internal .NET code.

In this specific case, there was a secondary issue with a member called value causing confusion; the csharp.xslt file has now been updated to account for this.


Update: in the fully managed rewrite, the ShouldSerialize*() method is generated by default when using proto2 syntax (the default). No additional parameter is required. The *Specified member is not added (it serves no additional purpose over ShouldSerialize*().

Note that when using proto3, the changes to serialization rules mean that this concept no longer has meaning. A value is serialized if and only if it is not the default, which is always null/false/zero/empty. There is no concept of "the default value but specified". Because of this, the ShouldSerialize*() methods are generally no longer useful, and are not generated. I'm open to making them optionally generated for proto3, with them basically meaning "non-default", if that helps some genuine coding scenario.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900