1. 程式人生 > >protobuf-c學習小結

protobuf-c學習小結

由於專案的需要,利用了一下午進行了protobuf-c的學習,下面來總結一下。

簡介:

protocolbuffer(以下簡稱PB)是google 的一種資料交換的格式,它獨立於語言,獨立於平臺。google 提供了三種語言的實現:javac++ 和 python,每一種實現都包含了相應語言的編譯器以及庫檔案。由於它是一種二進位制的格式,比使用 xml 進行資料交換快許多。可以把它用於分散式應用之間的資料通訊或者異構環境下的資料交換。作為一種效率和相容性都很優秀的二進位制資料傳輸格式,可以用於諸如網路傳輸、配置檔案、資料儲存等諸多領域。

專案中用到protobuf-c進行資料序列化,好處在於後期程式擴充套件性非常好,只需要改動proto的定義就可以保持相容,非常的靈活方便。

安裝:

由於我實在ubuntu下進行使用,所以安裝很方便,執行如下兩步就可以了:

<pre name="code" class="plain">1. 首先安裝protobuf。
sudo apt-get install protobuf-compiler libprotobuf-dev libprotoc-dev

2. 再而安裝protobuf-c
sudo apt-get install libprotobuf-c0-dev protobuf-c-compiler
編寫:

檔案格式:

message AMessage
{
     requried  int32  a = 1;  //a必須出現
     optional  string b = 2;  //b是可選的
     repeated  int32  c = 3;  //c是陣列
}
欄位規則型別:
required:表示後面的資料是必須的。

optional:表示後面資料是可選的。

repeated:表示後面的資料是一個數組。

下面就正式編寫一個.proto檔案:student.proto
message student
{
	required string id=1;
	required string name=2;
	required int32 age=3;
}
編譯:


分析:protoc-c就是編譯命令,--c_out=. 表示在當前目錄下生成.h和.c兩個檔案,最後面的就是原始檔。

測試:

student.proto:

message Student
{
	required string id=1;
	required string name=2;
	required int32 age=3;
}

enum Grade
{
	PRIMARY=0;
	JUNIOR=1;
	SENIOR=2;
	COLLEGE=3;
}

message School
{
	optional Grade grade=1[default=SENIOR];
	required Student student=2;
}

student_p.c:
/*************************************************************************
  > File Name: student_p.c
  > Author: AnSwEr
  > Created Time: 2015年04月10日 星期五 14時04分48秒
 ************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include "student.pb-c.h"
#include <string.h>

#define ID_LEN 11
#define NAME_LEN 11

int main()
{
	void *buf=NULL;
	unsigned  len;

	/*init*/
	Student stu ;
	student__init(&stu);
	School scl;
	school__init(&scl); 

	/*set student's value*/
	stu.id = malloc(ID_LEN);
	stu.name = malloc(NAME_LEN);
	strcpy(stu.name,"answer");
	strcpy(stu.id,"092312125");
	stu.age=22;
	
	/*set grade value*/
	Grade gra = GRADE__PRIMARY;
	
	/*set school value*/
	if(gra >= 0)
	{ 
		scl.has_grade = 1;
		scl.grade = gra;
	}
	scl.student = &stu;

	/*packing*/
	len = school__get_packed_size(&scl);
	buf = malloc(len);
	school__pack(&scl,buf);
	fprintf(stderr, "write %d serialized bytes\n",len);
	fwrite(buf,len,1,stdout);

	/*freeing*/
	free(buf);
	free(stu.id);
	free(stu.name);
	return 0;
}

student_up.c:
/*************************************************************************
  > File Name: student_up.c
  > Author: AnSwEr
  > Created Time: 2015年04月10日 星期五 14時13分52秒
 ************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include "student.pb-c.h"
#include <string.h>

#define MAX_MSG_LEN 1024

static size_t read_buff(unsigned max_length,uint8_t *out)
{
	size_t cur_len=0,nread=0;
	while((nread = fread(out+cur_len, 1, max_length - cur_len, stdin)) != 0)
	{
		cur_len += nread;
		if(cur_len == max_length)
		{
			fprintf(stderr,"max message length exceeded\n");
			exit(1);
		}
	}
	return cur_len;
}

int main()
{
	/*initing*/
	School *scl;
	school__init(scl);

	uint8_t buf[MAX_MSG_LEN];
	/*unpacking*/
	size_t  msg_len = read_buff(MAX_MSG_LEN,buf);
	scl = school__unpack(NULL,msg_len,buf);
	if(scl == NULL)
	{
		fprintf(stderr,"error unpacking incoming message\n");
		exit(1);
	}
	/*result*/
	if(scl->has_grade)
	{   
		switch(scl->grade)
		{
			case 0:
				printf("grade:primary\n");
				break;
			case 1:
				printf("grade:junior\n");
				break;
			case 2:
				printf("grade:senior\n");
				break;
			case 3:
				printf("grade:college\n");
				break;
			default:
				printf("grade unknow\n");
		}
	}
	printf("id:%s\n",scl->student->id);
	printf("name:%s\n",scl->student->name);
	printf("age:%d\n", scl->student->age);
	return 0;
}

編譯執行:


注意編譯時需要連結protobuf-c。

好啦,現在可以簡單的使用了。對於運用於專案開發而言,已經足夠了,就不再深入探討了。