Protocol Buffers
https://github.com/protocolbuffers/protobuf
설치
$ 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']))
잘되네..
'C & C++ 관련' 카테고리의 다른 글
C 에서 "Multiple definition of" "first defined here" 문제 (0) | 2023.04.12 |
---|---|
corrupted double-linked list (0) | 2016.12.30 |
file open close socket send / file copy~~~ example (0) | 2016.02.15 |