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