Friday, July 2, 2010

Very good HTML5 tutorials.

Awesome!

http://www.html5rocks.com/

http://www.chromeexperiments.com/

Thursday, July 1, 2010

Google Protocol Buffer 구글의 프로토콜 버퍼

Sometimes when we make data structure and use it for file i/o or network, writing manipulating functions is bothersome. Moreover it's a kind of stress when we have to use it over different environment or implementation. People tried to solve this matter for a long time(Maybe you've heard about XDR before). By the way, Google also faced the same and they were using what so called Google Protocol Buffer. It generates classes to manipulate our data structure expressed with .proto file for c++, python and java.

가끔식 특정 데이터 포맷 만들어 파일에 읽고 쓰거나 네트웍으로 전송할 일이 있을 때 이를 조작하는 함수들을 구현하고 테스트 하는 부분이 성가실 때가 있다. 특히 다른 환경(OS, 서버)이나 구현(언어)에서 동일하게 동작하는지 체크하는 과정은 시간을 잡아먹는다. 그래서 XDR같은 걸로 해결해 보려는 시도가 이전에 있었는데, 알고보니 구글에서도 비슷한 고민을 한거 같다. 얘네들은 구글 프로토콜 버퍼를 사용하는데, .proto 파일로 데이터 구조를 만들고 protoc로 컴파일 하면 c++, 파이썬, 자바로 관련 조작함수나 클래스를 생성해준다. 일종의 코드 제네레이터처럼.


package contacts;

message Person {
required int32 id = 1;
required string name = 2;
optional string email = 3;
}

This is a simple .proto file. We can compile this with protoc to generate code. Let me try to get a c++ code to manipulate this data format.

간단한 .proto 파일인데, protoc로 컴파일 할 수 있다. C++코드를 만들어보자.

> protoc contact.proto --cpp_out=.
> ls
contact.pb contact.pb.cc contact.pb.h contact.proto

Functions are defined in the header file above and you can also check it at the site. Ok. Now it's the time to use it.

조작함수는 구글 사이트나 contact.pb.h 헤더 파일을 보면 된다. 자, 그럼 한번 써볼까.


#include <iostream>
#include <fstream>
#include "contact.pb.h"
using namespace std;

static const string datafile = "contact.pb";

void pbWrite(int id, string name, string email)
{
Person person;
person.set_id(id);
person.set_name(name);
person.set_email(email);

fstream out(datafile.c_str(), ios::out|ios::binary|ios::trunc);
person.SerializeToOstream(&out);
out.close();
}

int pbRead(Person &p)
{
fstream in(datafile.c_str(), ios::in|ios::binary);
if(!p.ParseFromIstream(&in)) {
fprintf(stderr, "ERROR : Read Person from input stream\n");
return -1;
}
cout << p.DebugString();
/*
cout << "id : " << p.id() << endl;
cout << "name : " << p.name() << endl;
cout << "email : " << p.email() << endl;
*/
in.close();
}

int main()
{
GOOGLE_PROTOBUF_VERIFY_VERSION;

//pbWrite(12345, "Dustin Hyun", "dongseok.hyun@emailaddress.com");

Person p;
(void) pbRead(p);

return 0;
}

For version check, you should use macro GOOGLE_PROTOBUF_VERIFY_VERSION. Each member has get/set functions(see the code above). And you can serialize the data with SerializeToOstream() and parse from the file or stream with ParseFromIstream(). So cool and easy. This also works on the other implementation using python or java exactly the same way. It also support convenient functions like DebugString().

구글의 프로토콜 버퍼 버전 체크를 위해 GOOGLE_PROTOBUF_VERIFY_VERSION 매크로를 사용하고, 각 멤버들은 get/set 함수들이 있어 접근할 수 있다. 중요한것은,. 이런 데이터를 SerializeToOstream(), ParseFromIstream() 함수로 파일에 저장하거나 불러올 수 있고, 네트웍상에도 전달할 수 있다는 것. 겁나 편할 뿐 아니라 파이썬, 자바등 다른 언어로 구현된 코드들과도 호환되니 좋을 수밖에. C++로 서버를 구현하고 파이썬 qt로 짠 어플리케이션 클라이언트로 받아야 하는 상황이라면 완전 편하게 사용할 수 있다. DebugString() 같은 편리한 함수도 만들어주니 써보자 ^^;

Ps. don't forget to write -pthread 컴파일시 인스톨한 라이브러리 경로 넣어주는 거 잊지 말자.