由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 工具提取库的编译和连接参数有两个基本的前提:

  1. 库本身在安装的时候必须提供一个相应的 .pc 文件。不这样做的库说明不支持 pkg-config 工具的使用。
  2. 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” 问题解决方法

参考文献

  1. linux下g++ 编译时动态库和静态库的链接和头文件问题
  2. gcc/g++使用第三方库时添加头文件路径和库文件路径的方法
  3. Google Protocol Buffer 的使用和原理
  4. “undefined reference to” 问题解决方法
  5. 使用GCC和pkg-config编译
  6. 2.2 使用GCC 和pkg-config编译
  7. 详解pkg-config –cflags –libs glib-2.0的作用[转]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/258683.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

用python编写表达式求值_用Python3实现表达式求值

Problem Description yizhen has no girlfriend due to his stupid brain that he even can’t solve a simple arithmetic roblem. Can you help him If you solve it and tell him the result, then he can find his lovers! So beautiful! Input The input一、题目描述请用 …

the first day

开博第一天&#xff0c;从此记录我生活学习的点滴&#xff0c;加油转载于:https://www.cnblogs.com/fkissx/p/3702132.html

驱动-问题解决

今天在网上买了一个二手的电脑&#xff0c;拿回来以后&#xff0c;发现有点问题&#xff0c;一个问题就是 1.usb插上U盘以后没有反应 解决方法&#xff1a; 尝试一、直接在网上下载了一个360驱动大师&#xff0c;更新了一下驱动&#xff0c;没有解决 尝试二、在网上下载了一个驱…

Swift 学习- 02 -- 基础部分2

class NamedShape{ var numberOfSides: Int 0 var name: String init(name: String) { self.name name } func simpleDecription() -> String { return "A shape with \(numberOfSides) \(name) sides" } } // 除了储存简单的属性之外,属性可以有 getter 和 set…

R-CNN detection 运行问题及办法

运行caffe官方提供的jupyter 的rcnn detection&#xff0c;总是出现各种问题。先将问题及方法汇集在此&#xff1a; 1. Selective Search 的安装问题 按照官网&#xff0c;我下载了selective_search_ijcv_with_python&#xff0c;但是在我的linux matlab2017a上总是出现问题&…

python怎么用lambda和map函数_Python之lambda匿名函数及map和filter的用法

现有两个元组((a),(b)),((c),(d))&#xff0c;请使用python中匿名函数生成列表[{a:c},{b:d}]t1 ((a), (c))t2 ((b), (d))print(list(map(lambda t: {t[0]: t[1]}, zip(t1, t2))))l lambda t1, t2: [{i: j} for i, j in zip(t1, t2)]print(l(t1, t2))map内置函数使用&#xf…

UVALive 5903 Piece it together(二分图匹配)

给你一个n*m的矩阵&#xff0c;每个点为B或W或.。然后你有一种碎片。碎片可以旋转&#xff0c;问可否用这种碎片精确覆盖矩阵。N,M<500 WB 《碎片 W 题目一看&#xff0c;感觉是精确覆盖&#xff08;最近被覆盖洗脑了&#xff09;&#xff0c;但是仔细分析可以知道&#xf…

将undefault和null的数据转换成bool类型的数据 使用!!

<script> var o{}; var anull; console.info(!!o.name); </script> 输出false 此方法是将undefault和null的数据转换成bool类型的数据. var model avalon.define({ $id: model, defaultvalue {},});<span ms-if"!!defaultvalue .cost" >测试</…

springcloud(五):熔断监控Hystrix Dashboard和Turbine

Hystrix-dashboard是一款针对Hystrix进行实时监控的工具&#xff0c;通过Hystrix Dashboard我们可以在直观地看到各Hystrix Command的请求响应时间, 请求成功率等数据。但是只使用Hystrix Dashboard的话, 你只能看到单个应用内的服务信息, 这明显不够. 我们需要一个工具能让我们…

如何修改PKG_CONFIG_PATH环境变量

两种情况&#xff0c;如果你只是想加上某库的pkg&#xff0c;则选择下面其一&#xff1a;export PKG_CONFIG_PATH/usr/lib/pkgconfig/ 或者 export PKG_CONFIG_LIBDIR/usr/lib/pkgconfig/ 如果你想覆盖掉原来的pkg,选择后者。因为&#xff1a;PKG_CONFIG_LIBDIR的优先级比 PKG_…

python跨包导入包_python引入跨模块包

人生苦短&#xff0c;我学python。最近学习python&#xff0c;由于包的模块分的比较多。所以要用到跨模块引入 且调用中间的方法整体目录结构如下。需求&#xff1a;在 API模块 user.py 中 调用 plugin 模块中 douyin_login 下的方法。贴一下最终解决方案&#xff1a;from plug…

jdk1.8版本已经不包含jdbc.odbc连接

连接access的时候发现报错&#xff0c;无法加载jdbc.odbc类文件&#xff0c;到Java安装目录上jre/lib/rt.jar上找jdbcodbc类也没有了。 找个jdk1.7安装就ok啦。转载于:https://www.cnblogs.com/dohn/p/3707254.html

位运算问题

位运算 位运算是把数字用二进制表示之后&#xff0c;对每一位上0或者1的运算。 理解位运算的第一步是理解二进制。二进制是指数字的每一位都是0或者1.比如十进制的2转化为二进制之后就是10。在程序员的圈子里有一个流传了很久的笑话&#xff0c;说世界上有10种人&#xff0c;一…

conda环境管理介绍

我们可以使用conda 来切换不同的环境&#xff0c;主要的用法如下&#xff1a; 1. 创建环境 # 指定python版本为2.7&#xff0c;注意至少需要指定python版本或者要安装的包 # 后一种情况下&#xff0c;自动安装最新python版本conda create -n env_name python2.7# 同时安装必…

unable to execute dex: multiple dex files Cocos2dxAccelerometer

原文转载&#xff1a;http://discuss.cocos2d-x.org/t/conversion-to-dalvik-format-failed-unable-to-execute-dex-multiple-dex-files-define-lorg-cocos2dx-lib-cocos2dxaccelerometer/6652/4 用cocos2dx2.2.3没问题&#xff0c;用了3.1.1出现这个问题。确实够蛋疼。还要有这…

PHP javascript 值互相引用(不用刷新页面)

PHP javascript 值互相引用的问题 昨天通过EMAIL给一些公司投了简历&#xff0c;希望他们能给我一份工作&#xff0c;今天其中一家公司的人给我打电话&#xff0c;大意是要我做一点东西&#xff08;与AJAX有关&#xff09; 给他们看&#xff0c;我听打电话的人问我的问题&#…

mysql自增_面试官:为什么 MySQL 的自增主键不单调也不连续?

为什么这么设计(Why’s THE Design)是一系列关于计算机领域中程序设计决策的文章&#xff0c;我们在这个系列的每一篇文章中都会提出一个具体的问题并从不同的角度讨论这种设计的优缺点、对具体实现造成的影响。如果你有想要了解的问题&#xff0c;可以在文章下面留言。当我们在…

caffe 初学参考链接

最近在学习caffe&#xff0c;也搜集了一些资料&#xff0c;主要是一些网上公开的博客资源&#xff0c;现汇总一下&#xff0c;以便后面参考。 caffe 安装 编译py-faster-rcnn全过程caffe依赖库安装&#xff08;非root&#xff09;编译py-faster-rcnn的问题汇总及解决方法 ca…

java timer 定时任务

监听类1 package com.xx.model;2 3 import java.util.Calendar;4 import java.util.Date;5 import java.util.Timer;6 import javax.servlet.ServletContextEvent;7 import javax.servlet.ServletContextListener;8 import org.apache.commons.logging.Log;9 import org.apache…

python 打开txt_在python中从txt文件打开链接

我想请求一个rss程序的帮助。我所做的是收集包含我项目相关信息的网站&#xff0c;然后检查它们是否有rss提要。链接存储在txt文件中(每行一个链接)。因此&#xff0c;我有一个txt文件&#xff0c;其中包含了需要检查rss的基本url。在我找到了这个代码&#xff0c;这会使我的工…