Error while compiling protocol buffer on mac - c++

I am following the tutorial for protocol buffers and I keep running into different errors while compiling. my addressbook.proto file is in /Users/flexmaster411/protobuffer
protoc -I=/Users/flexmaster411/protobuffer --python_out= /Users/flexmaster411/protobuffer/addressbook.proto /Users/flexmaster411/protobuffer
I keep getting the following error even though I have syntax = "proto3" on my proto file
[libprotobuf WARNING google/protobuf/compiler/parser.cc:471] No syntax specified for the proto file. Please use 'syntax = "proto2";' or 'syntax = "proto3";' to specify a syntax version. (Defaulted to proto2 syntax.)
Not sure if I have correctly done the destination folders set up which is causing this or not Any help appreciated
syntax = "proto3";
package tutorial;
message Person {
string name = 1;
int32 id = 2; // Unique ID number for this person.
string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
string number = 1;
PhoneType type = 2;
}
repeated PhoneNumber phones = 4;
}
// Our address book file is just one of these.
message AddressBook {
repeated Person people = 1;
}

It looks like you reversed the order of the parameters. /Users/flexmaster411/protobuffer is your output directory, so it should appear with --python_out. Since you specified it second, protoc thinks you're telling it that /Users/flexmaster411/protobuffer is an input. So it's trying to open a directory and then parse it as a .proto file. Amusingly, read() on a directory returns no data, which protoc interprets as a perfectly valid .proto file that simply doesn't declare anything! But it then gives you a warning because this empty file doesn't have any syntax line.
I think what you meant to type is:
protoc -I=/Users/flexmaster411/protobuffer --python_out=/Users/flexmaster411/protobuffer /Users/flexmaster411/protobuffer/addressbook.proto

Related

"Too many message types specified in schema definition" when saving Schema

I would like to create this protobuf schema in google cloud pub/sub console.
I have a little local script where I successfully serialized and deserialized data with this schema with protobuf.
syntax = "proto2";
package mypackage;
message VideoImpression {
optional string user_id = 1;
optional string candidate_id = 2;
optional int64 event_timestamp = 3;
}
message VideoImpressionsList {
repeated VideoImpression video_impressions = 1;
}
When I save the schema I get this error:
Too many message types specified in schema definition.
I tried splitting both messages into seperate schema definitions but then it would complaint that e.g. when saving message VideoImpressionsList:
"VideoImpression" is not defined.
How can I make pub/sub to accept my above schema with two message types defined?
Thanks for any help
If you want to use one message type inside another, you should define one inside the other like this:
syntax = "proto2";
package mypackage;
message VideoImpressionsList {
message VideoImpression {
optional string user_id = 1;
optional string candidate_id = 2;
optional int64 event_timestamp = 3;
}
repeated VideoImpression video_impressions = 1;
}

How to create protobuf messages that use "oneof" definition

I'm trying to create 3 messages, start_now, stop_now, and HeartBeat,as defined in the .proto file below. I have already compiled the .proto file using the c++ compiler and have the necessary .h file. It is my understanding that the "oneof" definition allows for only one of the fields to be set at a time. My goal is to create a message,Serialize it using SerializeToString(), then on the receiving end I want to utilize the ParseToString() to get back my message in readable form.
syntax = "proto3";
package jomba;
message SimpleMessage {
}
message Jacket {
uint32 value = 1;
}
message Message {
oneof payload {
SimpleMessage start_now = 1;
SimpleMessage stop_now = 2;
Jacket heart_beat = 3;
}
}
Within the generated header file there is an enum created within class Message which shows the individual fields of the Message. I don't see any set_() functions within this class to generate any of the messages.
enum PayloadCase {
kStartNow = 1,
kStopNow = 2,
kHeartBeat = 3,
PAYLOAD_NOT_SET = 0,
};

C++ Protobuf, error when trying to build a FileDescriptor that imports another one

Currently I have the following two proto definitions, both .proto files are in same folder:
topmessage.proto:
syntax = "proto3";
message TopMessage {
// some fields
}
crestmessage.proto:
syntax = "proto3";
import "topmessage.proto";
message CrestMessage {
// some fields
TopMessage tm = 4;
}
Then, as part of my reader.cc, I am trying to build a file descriptor for the proto definition that user passes in. More specifically, the user will pass the path of the .proto file in as an argument, and the program will then read the file and build a file descriptor from it. Here is how this function is implemented, it mainly follows the blog by Floris https://vdna.be/site/index.php/2016/05/google-protobuf-at-run-time-deserialization-example-in-c/:
DescriptorPool pool;
const FileDescriptor* buildFileDescriptor(string file_path, string file_name) {
int def_messageFile = open(file_path.c_str(), O_RDONLY);
FileInputStream file_input(def_messageFile);
Tokenizer input(&file_input, NULL);
FileDescriptorProto file_desc_proto;
Parser parser;
if (!parser.Parse(&input, &file_desc_proto)) {
cerr << "Failed to parse .proto definition:" << endl;
return NULL;
}
file_desc_proto.set_name(file_name);
const FileDescriptor* file_desc = pool.BuildFile(file_desc_proto);
return file_desc;
}
The question now is when I am trying to build CrestMessage, and its proto definition file is also the one passed in as argument. For simplicity, I first build TopMessage by manually providing its file address since it is the dependency, and it works fine, and I can also find TopMessage in the pool, which is global. However, when I try to build CrestMessage, it gives the error.
const FileDescriptor* file_desc2 = buildFileDescriptor("topmessage.proto", "TopMessage");
cout << pool.FindFileByName("TopMessage") << endl;
const FileDescriptor* file_desc = buildFileDescriptor(definition_path, "CrestMessage");
cout << file_desc->name() << endl;
enter image description here
I have not find anything in the api description by Google that says how to import, does anyone have ideas on what should be used?
it's a name problem, instead of using message name when building FileDescriptor, use the name of the .proto file ("topmessage.proto" for example)

protobuf for configuration files

Related to using protobuf as a textual configuraton file I'd like to use protobuf for configuration file.
I expect that protobuf allows me to use simple parser with exact structure.
My configuration structure looks like
//my.proto
package my_config;
message MyConfigItem {
required string type = 1;
required string name = 2;
repeated string inputNames = 3 [packed=true];
repeated string outputNames = 4 [packed=true];
}
And bunch of different items in config files like
MyConfigItem {
type = "type1";
name = "name1";
inputNames = {"input1", "input2"};
}
What's the best way for organizing that?
You may write config file like:
type : "type1"
name : "name1"
inputNames : {"input1", "input2"}
So I think that you must use ':' instead of '=', and "do not" write the items wrapped in the brackets.

Is it possible to restore the .proto file when a message uses package, imports, and field options?

My goal is to restore the lost .proto files written by someone else from existing c++ protobuf messages. By using the Descriptor and EnumDescriptor I was able to do the following:
const google::protobuf::EnumDescriptor* logOptionDesc =
bgs::protocol::LogOption_descriptor();
std::string logOptionStr = logOptionDesc->DebugString();
bgs::protocol::EntityId entityId;
const google::protobuf::Descriptor* entityIdDesc = entityId.GetDescriptor();
std::string entityIdStr = entityIdDesc->DebugString();
The logOptionStr string I got looked something like this:
enum LogOption {
HIDDEN = 1;
HEX = 2;
}
and entityIdStr:
message EntityId {
required fixed64 high = 1 [(.bgs.protocol.log) = HEX];
required fixed64 low = 2 [(.bgs.protocol.log) = HEX];
}
Notice the EntityId message contains some field options. Without resolving this dependency I cannot generate a FileDescriptor that can help me restore the .proto files. I suspect the EntityId string should look something like the following:
import "LogOption.proto";
package bgs.protocol;
extend google.protobuf.FieldOptions {
optional LogOptions log = HEX;
}
message EntityId {
required fixed64 high = 1 [(.bgs.protocol.log) = HEX];
required fixed64 low = 2 [(.bgs.protocol.log) = HEX];
}
Is it possible to restore the .proto files that require additional information such as package, field options and imports? What else do I need to do to restore the .proto files?