Protocol Buffers

C & C++ 관련 : 2019. 11. 8. 13:20
반응형

https://github.com/protocolbuffers/protobuf

 

protocolbuffers/protobuf

Protocol Buffers - Google's data interchange format - protocolbuffers/protobuf

github.com

설치

$ sudo apt-cache search protobuf | grep -i proto

그 중에 C++ 라이브러리 설치.

$ sudo apt-get install libprotobuf-dev

컴파일러 설치 

$ sudo apt-get install protobuf-compiler

person.proto 를 만듬.

  1 syntax="proto3";
  2 message Person{
  3         string name = 1; //필수
  4         int32 id = 2;
  5         repeated string email = 3; //배열
  6         enum PhoneType{
  7                 MOBILE = 0;
  8                 HOME = 1;
  9                 WORK = 2;
 10         }
 11         message PhoneNumber{
 12                 string number = 1;
 13                 PhoneType type = 2;
 14         }
 15         repeated PhoneNumber phone = 4; //배열
 16 }

이렇게.

만든것을 컴파일 함. 난 C++ 용으로 만듬.

$ protoc -I=./ --cpp_out=./ ./person.proto

이렇게 하면

-rw-rw-r--  1 lionelj lionelj  18K 11월  8 13:27 person.pb.cc
-rw-rw-r--  1 lionelj lionelj 9.3K 11월  8 13:27 person.pb.h
-rw-rw-r--  1 lionelj lionelj  118 11월  8 13:27 person.proto

h랑 cc 가 생김.

참고로 Proto3 에서는 optional , default, reqired 없어짐.

person.proto:12:26: Explicit 'optional' labels are disallowed in the Proto3 syntax. To define 'optional' fields in Proto3, simply remove the 'optional' label, as fields are 'optional' by default.

person.proto: Explicit default values are not allowed in proto3.
person.proto: Required fields are not allowed in proto3.

person.proto: Required fields are not allowed in proto3.

 

테스트 하기 위해서 프로그램을 이렇게 짬.

| 382 int main(int argc, char **argv)
| 383 {
| 384         Person p1;
| 385         Person_PhoneNumber pnumber;
| 386         p1.set_name("lionel.j");
| 387         p1.set_id(1);
| 388         p1.add_email("lionel.j@gmail.com");
| 389 
| 390         ofstream output("myfile", ios::out|ios::binary);
| 391         p1.SerializeToOstream(&output);
| 392         output.close();
| 393 
| 394         ifstream input("myfile", ios::in|ios::binary);
| 395         Person person;
| 396         person.ParseFromIstream(&input);
| 397         input.close();
| 398 
| 399         cout << "Name: " << person.name() << endl;
| 400         cout << "E-mail: " << person.email(0) << endl;
| 401 }

파일에 시리얼라이즈드되서 써짐. 

이제 이 파일을 python 으로 열어볼 것임.

같은 person.proto 를 가지고

$ protoc -I=./ --python_out=./ ./person.proto 

하면 person_pb2.py 가 생김

파이썬 2.7용 라이브러리를 설치

$ sudo apt-get install python-protobuf

그런데 하다보니 python 에는 ParseFromIstream 에 해당하는게 없는것 같다.

>>> from person_pb2 import Person
>>> p1 = Person()
>>> dic(p1)
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'dic' is not defined
>>> dir(p1)
['ByteSize', 'Clear', 'ClearExtension', 'ClearField', 'CopyFrom', 'DESCRIPTOR', 'DiscardUnknownFields', 'EMAIL_FIELD_NUMBER', 'Extensions', 'FindInitializationErrors', 'FromString', 'HOME', 'HasExtension', 'HasField', 'ID_FIELD_NUMBER', 'IsInitialized', 'ListFields', 'MOBILE', 'MergeFrom', 'MergeFromString', 'NAME_FIELD_NUMBER', 'PHONE_FIELD_NUMBER', 'ParseFromString', 'PhoneNumber', 'PhoneType', 'RegisterExtension', 'SerializePartialToString', 'SerializeToString', 'SetInParent', 'WORK', 'WhichOneof', '_CheckCalledFromGeneratedFile', '_SetListener', '__class__', '__deepcopy__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', '__unicode__', '__weakref__', '_extensions_by_name', '_extensions_by_number']

ParseFromString 이걸로 해야되는건가.

안맞는것 같지만 C++ 에서 또 바꾸기 귀찮으니까 그냥 해본다.

  1 from person_pb2 import Person
  2 
  3 if __name__ == "__main__":
  4     with open("myfile", 'rb') as file:
  5         content = file.read()
  6         print("Retrieve Person object from myfile")
  7         p1 = Person()
  8         p1.ParseFromString(content)
  9         print("Person name: ", {p1.name})
 10         print("Person id: ", {p1.id})
 11         print("Person email: ", {p1.email[0]})

$ python ./test.py 
Retrieve Person object from myfile
('Person name: ', set([u'lionel.j']))
('Person id: ', set([1]))
('Person email: ', set([u'lionel.j@gmail.com']))

잘되네..

반응형
Posted by Real_G