日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

由Google Protocol Buffer的小例子引起的g++编译问题

發布時間:2023/12/10 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 由Google Protocol Buffer的小例子引起的g++编译问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

問題

學習 Google Protocol Buffer 的使用和原理時,提供了一個小例子,講述了protobuf的使用方法。

假如已經有了如下文件:




其中writer.cpp如下:

#include "lm.helloworld.pb.h" #include<iostream> #include<fstream> using namespace std;int main(void) { lm::helloworld msg1; msg1.set_id(101); msg1.set_str("hello"); // Write the new address book back to disk. fstream output("./log", ios::out | ios::trunc | ios::binary); if (!msg1.SerializeToOstream(&output)) { cerr << "Failed to write msg." << endl; return -1; } return 0; }

reader.cpp如下:

#include "lm.helloworld.pb.h" #include<iostream> #include<fstream> using namespace std;void ListMsg(const lm::helloworld & msg) { cout << msg.id() << endl; cout << msg.str() << endl; } int main(int argc, char* argv[]){ lm::helloworld msg1; { fstream input("./log", ios::in | ios::binary); if (!msg1.ParseFromIstream(&input)){ cerr << "Failed to parse address book." << endl; return -1; } } ListMsg(msg1); return 0;}

可以看到writer.cpp與reader.cpp都用到了lm.helloworld.pb.h,它的實現文件也在該目錄下。
那么如何編譯writer同樣reader呢?

方法

解析

這里有兩個問題,一個是writer與reader都引用到了lm.helloworld.pb.h,故實際上先需要編譯lm.helloworld.pb.cc才能被前者使用。 第二個是編譯lm.helloworld.pb.cc時需要用到第三方庫protobuf。
下面我們從后往前解決。

g++鏈接用到第三方庫

有兩種方法,
一種就是直接使用-L,-I,-l等參數直接告訴g++需要鏈接到哪些,比如:

gcc -o hello hello.c -I /home/hello/include -L /home/hello/lib -lworld

可以參考1. linux下g++ 編譯時動態庫和靜態庫的鏈接和頭文件問題
2. gcc/g++使用第三方庫時添加頭文件路徑和庫文件路徑的方法
第二種方法就是使用pkg-config
pkg-config 是通過庫提供的一個 .pc 文件獲得庫的各種必要信息的,包括版本信息、編譯和連接需要的參數等。這些信息可以通過 pkg-config 提供的參數單獨提取出來直接供編譯器和連接器使用。
在默認情況下,每個支持 pkg-config 的庫對應的 .pc 文件在安裝后都位于安裝目錄中的 lib/pkgconfig 目錄下。例如,我們安裝一個叫Glib 的庫,且將其安裝在 /opt/gtk 目錄下了,那么這個 Glib 庫對應的 .pc 文件是 /opt/gtk/lib/pkgconfig 目錄下一個叫 glib-2.0.pc 的文件:

prefix=/opt/gtk/ exec_prefix=${prefix} libdir=${exec_prefix}/lib includedir=${prefix}/includeglib_genmarshal=glib-genmarshal gobject_query=gobject-query glib_mkenums=glib-mkenumsName: GLib Description: C Utility Library Version: 2.12.13 Libs: -L${libdir} -lglib-2.0 Cflags: -I${includedir}/glib-2.0 -I${libdir}/glib-2.0/include

使用 pkg-config 的 –cflags 參數可以給出在編譯時所需要的選項,而 –libs 參數可以給出連接時的選項。例如,假設一個 sample.c 的程序用到了 Glib 庫,就可以這樣編譯,得到sample.o:

$ gcc -c `pkg-config --cflags glib-2.0` sample.c

然后這樣連接

$ gcc sample.o -o sample `pkg-config --libs glib-2.0`

或者上面兩步也可以合并為以下一步:

$ gcc sample.c -o sample `pkg-config --cflags --libs glib-2.0`

從上面的pkgconfig 可以看到cflags, libs 分別指頭文件與庫的路徑。

可以看到:由于使用了 pkg-config 工具來獲得庫的選項,所以不論庫安裝在什么目錄下,都可以使用相同的編譯和連接命令,帶來了編譯和連接界面的統一。

使用 pkg-config 工具提取庫的編譯和連接參數有兩個基本的前提:

  • 庫本身在安裝的時候必須提供一個相應的 .pc 文件。不這樣做的庫說明不支持 pkg-config 工具的使用。
  • pkg-config 必須知道要到哪里去尋找此 .pc 文件。
    后者可以在~/.bashrc中設置:
  • export PKG_CONFIG_PATH=/opt/gtk/lib/pkgconfig:$PKG_CONFIG_PATH

    g++鏈接用到另外一個源文件

    可以使用兩種方法,一種就是先編譯lm.helloworld.pb.cc,再編譯writer,reader,即:

    $ g++ -c lm.helloworld.pb.cc $ g++ -c writer.cpp $ g++ writer.o lm.helloworld.pb.o -o writer `pkg-config --cflags --libs protobuf` $ ./writer

    或者

    $ g++ -c lm.helloworld.pb.cc `pkg-config --cflags protobuf` $ g++ -c reader.cpp $ g++ reader.o lm.helloworld.pb.o -o reader `pkg-config --libs protobuf` $ ./reader 101 hello

    第二種方法就是:

    $ g++ -o reader reader.cpp lm.helloworld.pb.cc `pkg-config --cflags --libs protobuf` $ ./reader 101 hello

    可以參考“undefined reference to” 問題解決方法

    參考文獻

  • linux下g++ 編譯時動態庫和靜態庫的鏈接和頭文件問題
  • gcc/g++使用第三方庫時添加頭文件路徑和庫文件路徑的方法
  • Google Protocol Buffer 的使用和原理
  • “undefined reference to” 問題解決方法
  • 使用GCC和pkg-config編譯
  • 2.2 使用GCC 和pkg-config編譯
  • 詳解pkg-config –cflags –libs glib-2.0的作用[轉]
  • 總結

    以上是生活随笔為你收集整理的由Google Protocol Buffer的小例子引起的g++编译问题的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。