-
[Protocol Buffer] google protobuf 란Computer Programs 2021. 6. 29. 18:23
https://yoongrammer.tistory.com/14
구글에서 오픈소스로 공개한 구조화된 데이터를 직렬화 하는 방식. ( structured data serialization )
protocol buffer원리
person 객체를 json으로 person 객체 스키마 스키마 사용해서 json 데이터를 인코딩하면 protobuf는 다른 IDL ( XML, JSON ) 에 비해 더 적은 용량으로 데이터를 저장할 수 있기 때문에 압축률이 좋고 처리속도가 빠르다.
하지만 바이너리 데이터로 표현되기 떄문에 확인하기 어렵다.
protocol buffer 사용방법
protocol buffer 사용흐름
1. *.proto 파일에서 메시지 형식 작성
2. protoc 컴파일러를 통해 원한는 언어로 컴파일
3. 프로토콜 버퍼를 사용하는 전체목적은 데이터를 다른 곳에서 구문 분석 할 수 있도록 직렬화, 인코딩 ( 마샬링 )
4. 직렬화된 데이터를 사용하기 위해 디코딩 ( 언마샬링 )
https://developers.google.com/protocol-buffers/docs/cpptutorial
protocol buffer basic tutorial
how to
1. define message formate in *.proto file
2. use the protocol buffer compiler
3. use c++ protocol buffer api to write and read messages
protoc 컴파일러 설치
https://github.com/protocolbuffers/protobuf/releases
mac os는
brew install protobuf
잘깔렸는지 확인은 protoc --version
protocol format을 먼저 정의
-> Addressbook.proto 파일 만들기
ROS에서 custom message만드는 것과 비슷.
syntax = "proto2"; package tutorial; message Person { optional string name = 1; optional int32 id = 2; optional string email = 3; enum PhoneType { MOBILE = 0; HOME = 1; WORK = 2; } message PhoneNumber { optional string number = 1; optional PhoneType type = 2 [default = HOME]; } repeated PhoneNumber phones = 4; } message AddressBook { repeated Person people = 1; }
protofile은 package declaration으로 시작.
c++ 프로젝트에서 package 이름으로 namespace가 생성되어서 사용할 수 있게 된다.
여기서는 tutorial 이므로 tutorial::AddressBook
그다음에 protoc 사용해서 protocol buffers 컴파일.
protoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/addressbook.proto
protoc -I=. --cpp_out=. addressbook.proto
컴파일 하면 .pb.h 헤더 파일이랑 .pb.cc 파일이 생성된다.
addressbook.pb.h 파일 안에 생성된 setter getter 함수들
protoc으로 컴파일 하면서 자동으로 생성된 함수들을 가지고 proto buf 사용 테스트
addressbook.data 파일을 만들고, 해당 파일안에 address 정보들을 입력하는 소스코드
//write.cpp #include <iostream> #include <fstream> #include <string> #include "addressbook.pb.h" using namespace std; // This function fills in a Person message based on user input. void PromptForAddress(tutorial::Person* person) { cout << "Enter person ID number: "; int id; cin >> id; person->set_id(id); cin.ignore(256, '\n'); cout << "Enter name: "; getline(cin, *person->mutable_name()); cout << "Enter email address (blank for none): "; string email; getline(cin, email); if (!email.empty()) { person->set_email(email); } while (true) { cout << "Enter a phone number (or leave blank to finish): "; string number; getline(cin, number); if (number.empty()) { break; } tutorial::Person::PhoneNumber* phone_number = person->add_phones(); phone_number->set_number(number); cout << "Is this a mobile, home, or work phone? "; string type; getline(cin, type); if (type == "mobile") { phone_number->set_type(tutorial::Person::MOBILE); } else if (type == "home") { phone_number->set_type(tutorial::Person::HOME); } else if (type == "work") { phone_number->set_type(tutorial::Person::WORK); } else { cout << "Unknown phone type. Using default." << endl; } } } // Main function: Reads the entire address book from a file, // adds one person based on user input, then writes it back out to the same // file. int main(int argc, char* argv[]) { // Verify that the version of the library that we linked against is // compatible with the version of the headers we compiled against. GOOGLE_PROTOBUF_VERIFY_VERSION; if (argc != 2) { cerr << "Usage: " << argv[0] << " ADDRESS_BOOK_FILE" << endl; return -1; } tutorial::AddressBook address_book; { // Read the existing address book. fstream input(argv[1], ios::in | ios::binary); if (!input) { cout << argv[1] << ": File not found. Creating a new file." << endl; } else if (!address_book.ParseFromIstream(&input)) { cerr << "Failed to parse address book." << endl; return -1; } } // Add an address. PromptForAddress(address_book.add_people()); { // Write the new address book back to disk. fstream output(argv[1], ios::out | ios::trunc | ios::binary); if (!address_book.SerializeToOstream(&output)) { cerr << "Failed to write address book." << endl; return -1; } } // Optional: Delete all global objects allocated by libprotobuf. google::protobuf::ShutdownProtobufLibrary(); return 0; }
//read.cpp #include <iostream> #include <fstream> #include <string> #include "addressbook.pb.h" using namespace std; // Iterates though all people in the AddressBook and prints info about them. void ListPeople(const tutorial::AddressBook& address_book) { for (int i = 0; i < address_book.people_size(); i++) { const tutorial::Person& person = address_book.people(i); cout << "Person ID: " << person.id() << endl; cout << " Name: " << person.name() << endl; if (person.has_email()) { cout << " E-mail address: " << person.email() << endl; } for (int j = 0; j < person.phones_size(); j++) { const tutorial::Person::PhoneNumber& phone_number = person.phones(j); switch (phone_number.type()) { case tutorial::Person::MOBILE: cout << " Mobile phone #: "; break; case tutorial::Person::HOME: cout << " Home phone #: "; break; case tutorial::Person::WORK: cout << " Work phone #: "; break; } cout << phone_number.number() << endl; } } } // Main function: Reads the entire address book from a file and prints all // the information inside. int main(int argc, char* argv[]) { // Verify that the version of the library that we linked against is // compatible with the version of the headers we compiled against. GOOGLE_PROTOBUF_VERIFY_VERSION; if (argc != 2) { cerr << "Usage: " << argv[0] << " ADDRESS_BOOK_FILE" << endl; return -1; } tutorial::AddressBook address_book; { // Read the existing address book. fstream input(argv[1], ios::in | ios::binary); if (!address_book.ParseFromIstream(&input)) { cerr << "Failed to parse address book." << endl; return -1; } } ListPeople(address_book); // Optional: Delete all global objects allocated by libprotobuf. google::protobuf::ShutdownProtobufLibrary(); return 0; }
컴파일은
g++ -std=c++17 read.cpp addressbook.pb.cc -o read -L/usr/local/lib -lprotobuf
protobuf만 그런지 아니면 딴것들도 그런지는 모르게찌만
생성된 pb.cc 도 참조로 같이 컴파일 해줘야지 된다!
실행은 실행파일뒤에 addressbook.data ( 데이터 파일 이름 ) 적고 실행
read 해서 확인하면
요로코롬~~~~
https://gist.github.com/madelinegannon/393fe7b1a24664abd0976467162f5f14
'Computer Programs' 카테고리의 다른 글
[Capnp] Cap'n Proto 란 (0) 2022.11.07 [ZeroMQ] Socket 생성 및 동작 확인 및 구현 (0) 2021.06.29 [ZeroMQ] Mac Os BigSur & Linux Ubuntun 18.04 에서 설치 및 helloworld 테스트 (0) 2021.06.28 [CMake] CMakeLists.txt 작성하기 (0) 2021.06.28