干貨!protobuf-c之嵌入式平臺(tái)使用
什么是protobuf-c
之前的文章:《Protobuf:一種更小、更快、更高效的協(xié)議》詳細(xì)介紹了protobuf及protobuf-c。這里再簡單提一下:
Protocol Buffers
,是Google公司開發(fā)的一種數(shù)據(jù)格式,類似于XML能夠?qū)⒔Y(jié)構(gòu)化數(shù)據(jù)序列化,可用于數(shù)據(jù)存儲(chǔ)、通信協(xié)議等方面。protobuf支持一些主流的語言,唯獨(dú)沒有支持C,所以誕生了第三方的protobuf-c。
之前文章介紹了protobuf、protobuf-c在PC平臺(tái)上的安裝及使用,本篇筆記我們來把它用在我們的嵌入式ARM平臺(tái)。
交叉編譯protobuf-c
之前的文章中我們已經(jīng)把protobuf、protobuf-c安裝在我們的PC環(huán)境中了:
我們簡單回顧一下我們上一篇文章的大致內(nèi)容:
從中我們知道,這里的protobuf的主要作用是生成了protoc工具,而protoc工具的作用是把.proto文件生成對(duì)應(yīng)的C源、頭文件,這個(gè)過程是與平臺(tái)無關(guān)的,所以這里我們可以接著用。
而protobuf-c生成了編譯需要用到的動(dòng)態(tài)庫,此處我們需要編譯ARM架構(gòu)的動(dòng)態(tài)庫。即我們本篇筆記需要做的事情是:
(1)交叉編譯protobuf-c
首先在protobuf-c目錄下使用make clean
命令清除我們之前編譯得到的東西:
輸入如下命令生成交叉編譯的Makefile文件:
左右滑動(dòng)查看全部代碼>>>
./configure?--host=arm-linux-gnueabihf?CC=/home/book/ToolChain/gcc-arm-linux-gnueabihf-6.2.1/bin/arm-linux-gnueabihf-gcc?CXX=/home/book/ToolChain/gcc-arm-linux-gnueabihf-6.2.1/bin/arm-linux-gnueabihf-g++?--disable-protoc?--prefix=$PWD/tmp
這個(gè)命令似乎很長,但并不難,只是加了幾個(gè)配置參數(shù)。這些配置參數(shù)怎么看?我們可以輸入./configure --help
命令來查看支持的配置:
下面我們依次來分析上面那個(gè)很長的命令:
-
--host=arm-linux-gnueabihf:表明了我們最終可執(zhí)行文件運(yùn)行的環(huán)境。
-
CC=/home/book/ToolChain/gcc-arm-linux-gnueabihf-6.2.1/bin/arm-linux-gnueabihf-gcc:這是指定我們的交叉編譯工具arm-linux-gnueabihf-gcc,這里直接給出絕對(duì)路徑。
-
CXX=/home/book/ToolChain/gcc-arm-linux-gnueabihf-6.2.1/bin/arm-linux-gnueabihf-g++:這是指定我們的交叉編譯工具arm-linux-gnueabihf-g++,這里直接給出絕對(duì)路徑。
-
--disable-protoc:不使用protoc,前面我們也說了protoc工具把.proto文件生成對(duì)應(yīng)的C源、頭文件的過程是與平臺(tái)無關(guān)的,所以這里不需要使用,除非我們想在我們的開發(fā)板上使用protoc,但這反而增加麻煩,不推薦直接在開發(fā)板上用。
-
--prefix=$PWD/tmp:指定安裝的路徑。表明安裝路徑在當(dāng)前路徑下的tmp文件夾中。
執(zhí)行完這個(gè)命令之后就得到了交叉編譯的Makefile文件,然后依次輸入如下命令進(jìn)行編譯、安裝:
make
make?install
此時(shí)就在當(dāng)前目錄的tmp文件夾下生成了arm版本的相關(guān)庫文件:
其中我們比較重要的就是libprotobuf-c.so
這個(gè)動(dòng)態(tài)庫了,我們可以使用file或者readelf工具查看其是不是arm格式的:
很顯然,這就是我們ARM平臺(tái)的動(dòng)態(tài)庫。關(guān)于readelf的使用相關(guān)文章:《簡單認(rèn)識(shí)認(rèn)識(shí)ELF文件》
下面開始我們的demo演示:
(2)protobuf-c實(shí)例演示
我們自定義一個(gè).proto
來創(chuàng)建我們的協(xié)議數(shù)據(jù),然后使用protoc-c工具
編譯生成C代碼,有兩個(gè)文件:一個(gè)頭文件、一個(gè)源文件。
例如我們創(chuàng)建一個(gè)student.proto
文件:
syntax?=?"proto2";
?
message?Student
{
????required?string?name????=?1;
????required?uint32?num?????=?2;
????required?uint32?c_score?=?3;
}
使用protoc-c工具
工具編譯student.proto
文件:
protoc?--c_out=.?student.proto
編寫我們的student.c測(cè)試demo:
左右滑動(dòng)查看全部代碼>>>
#include?
#include?
#include?
#include?"student.pb-c.h"
?
int?main(void)
{
????Student?pack_stu?=?{0};
????uint8_t?buffer[512]?=?{0};
????Student?*unpack_stu?=?NULL;
????size_t?len?=?0;
?
????student__init(&pack_stu);
?
????/*?組包?*/
????pack_stu.name?=?"ZhengN";
????pack_stu.num?=?88;
????pack_stu.c_score?=?90;
????len?=?student__pack(&pack_stu,?buffer);
????printf("len?=?%ld\n",len);
?
????/*?解包?*/
????unpack_stu?=?student__unpack(NULL,?len,?buffer);
????printf("unpack_stu.name?=?%s\n",?unpack_stu->name);
????printf("unpack_stu.num?=?%d\n",?unpack_stu->num);
????printf("unpack_stu.c_score?=?%d\n",?unpack_stu->c_score);
?
????student__free_unpacked(unpack_stu,?NULL);
????return?0;
}
demo很簡單,組包就是構(gòu)造一個(gè)協(xié)議數(shù)據(jù)結(jié)構(gòu)體,調(diào)用pack組包接口往buffer中扔數(shù)據(jù);解包正好是反過來,從buffer中拿數(shù)據(jù)放到結(jié)構(gòu)體里。
此時(shí)我們工程的文件有:
交叉編譯:
左右滑動(dòng)查看全部代碼>>>
arm-linux-gnueabihf-gcc?student.c?student.pb-c.c?-o?student?-I?/home/book/git_clone/protobuf-c/tmp/include?-L?/home/book/git_clone/protobuf-c/tmp/lib?-lprotobuf-c
這個(gè)命令似乎也很長,其實(shí)也很簡單:
-
arm-linux-gnueabihf-gcc:交叉編譯器。 -
student.c student.pb-c.c:輸入的源文件。 -
student:生成的可執(zhí)行文件。 -
-I /home/book/git_clone/protobuf-c/tmp/include:指定頭文件路徑。 -
-L /home/book/git_clone/protobuf-c/tmp/lib:指定庫路徑。 -
-lprotobuf-c:鏈接動(dòng)態(tài)庫libprotobuf-c.so。
這里需要重點(diǎn)提的就是我們可以把我們上面編譯得到的tmp/include里的文件復(fù)制到我們交叉編譯器頭文件搜索路徑下、把tmp/lib里的文件復(fù)制到交叉編譯器庫文件搜索路徑下,這樣我們就不需要指定這么長的一串路徑了。
但是這里我為了保持我的交叉編譯器的一個(gè)原始性,我就不往里加?xùn)|西了。關(guān)于這些鏈接、動(dòng)態(tài)庫更詳細(xì)的內(nèi)容可以閱讀往期文章:《靜態(tài)鏈接與動(dòng)態(tài)鏈接補(bǔ)充(Linux)》、《什么是動(dòng)態(tài)鏈接與靜態(tài)鏈接?》
編譯沒問題的話就可以生成我們的可執(zhí)行文件student:
同樣的,我們可以看一下student可執(zhí)行文件的運(yùn)行環(huán)境:
可見,是可運(yùn)行在我們的arm開發(fā)板的。
下面把student拷貝到我們的開發(fā)板上運(yùn)行,我這里用的是韋東山老師的IMX6ULL開發(fā)板。
運(yùn)行出現(xiàn)如下錯(cuò)誤:
這是因?yàn)椴荒苷业焦蚕韼煳募ibprotobuf-c.so1,加載失敗,這個(gè)問題我們已經(jīng)在《靜態(tài)鏈接與動(dòng)態(tài)鏈接補(bǔ)充(Linux)》一文中做了詳細(xì)解釋。
解決方法有兩種:第一種就是把這個(gè)庫文件拷貝至系統(tǒng)庫默認(rèn)搜索路徑下;第一種就是把當(dāng)前路徑增加為動(dòng)態(tài)庫的搜索路徑。
這里我們選擇第二種方法:我們把libprotobuf-c.so、libprotobuf-c.so1也傳到板子上,放在student同目錄下。然后輸入如下命令把當(dāng)前路徑增加為動(dòng)態(tài)庫的搜索路徑:
export?LD_LIBRARY_PATH=./:$LD_LIBRARY_PATH
然后運(yùn)行:
運(yùn)行成功!
以上就是咱們介紹的protobuf-c在嵌入式Linux平臺(tái)上的使用(如果是正在學(xué)單片機(jī)的朋友,也可以嘗試著移植使用。),如有錯(cuò)誤,歡迎指出,謝謝。
按照以上兩篇文章的步驟,大概率是可以成功的,關(guān)鍵是有耐心。
心得分享:在Linux的學(xué)習(xí)中,很多時(shí)候會(huì)被開發(fā)環(huán)境阻礙我們。常常按照別人的方法、步驟來做,卻做不出來,很容易心態(tài)崩,這都是很正常的。因?yàn)榄h(huán)境不同,有時(shí)候還需要各種依賴。但我們要有足夠的耐心,見招拆招!
在此之前,我也遇到了很多問題,也搜索了很多博客文章,要么行不通,要么寫得太亂。所以趁此學(xué)習(xí)、寫一篇。
這一篇大概是全網(wǎng)第一篇關(guān)于protobuf-c在嵌入式Linux平臺(tái)上的交叉編譯、使用步驟最全、解釋最多的文章了。如果文章對(duì)你有幫助,麻煩幫忙轉(zhuǎn)發(fā),謝謝大家。
最后
以上就是本次的分享,如果覺得文章不錯(cuò),轉(zhuǎn)發(fā)、在看,也是我們繼續(xù)更新的動(dòng)力。
猜你喜歡:
2020年精選原創(chuàng)筆記匯總
干貨 | 深度剖析C語言的main函數(shù)
Linux 的啟動(dòng)流程
1024G 嵌入式資源大放送!包括但不限于C/C++、單片機(jī)、Linux等。在公眾號(hào)聊天界面回復(fù)1024,即可免費(fèi)獲??!
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場,如有問題,請(qǐng)聯(lián)系我們,謝謝!