参考https://blog.csdn.net/jcjc918/article/details/50876613

安装:

  1. git clone https://github.com/gflags/gflags.git # 下载源码
  2. cd gflags
  3. mkdir build && cd build # 建立文件夹
  4. cmake .. # 使用 cmake 编译生成 Makefile 文件
  5. make # make 编译
  6. sudo make install # 安装库

这时 gflags 库会默认安装在 /usr/local/lib/ 下,头文件放在 /usr/local/include/gflags/ 中。

使用:

假设有一个程序,需要知道服务器的IP地址和端口号,在程序中有默认的指定参数,同时也希望通过命令行来指定不同的值。

  1. #include <iostream>
  2.  
  3. #include <gflags/gflags.h>
  4.  
  5. DEFINE_string(host, "127.0.0.1", "the server host");
  6. DEFINE_int32(port, , "the server port");
  7.  
  8. int main(int argc, char** argv) {
    //程序使用说明
    google::SetUsageMessage("\nusage\n");
  9. // 解析命令行参数,一般都放在 main 函数中开始位置
  10. gflags::ParseCommandLineFlags(&argc, &argv, true);
  11. // 访问参数变量,加上 FLAGS_
  12. std::cout << "The server host is: " << FLAGS_host
  13. << ", the server port is: " << FLAGS_port << std::endl;
  14. return ;
  15. }

编译运行:

CMakeLists.txt

  1. cmake_minimum_required(VERSION 2.8)
  2. project(gflags_test)
  3. set( CMAKE_BUILD_TYPE "Debug" )
  4. find_package (gflags REQUIRED)
  5. include_directories (${gflags_INCLUDE_DIR})
  6.  
  7. add_executable (gflags_test gflags_test.cc)
  8. target_link_libraries (gflags_test gflags)

cmake . && make

  1. ./gflags_test #不带任何参数
  2. The server host is: 127.0.0.1, the server port is:
  3. ./gflags_test -host 10.123.78.90 #只带 host 参数
  4. The server host is: 10.123.78.90, the server port is:
  5. ./gflags_test -port # 只带 port 参数
  6. The server host is: 127.0.0.1, the server port is:
  7. ./gflags_test -host 10.123.78.90 -port # host 和 port 参数
  8. The server host is: 10.123.78.90, the server port is:
  9. ./gflags_test --host 10.123.78.90 --port # 用 -- 指定
  10. The server host is: 10.123.78.90, the server port is:
  11. ./gflags_test --host=10.123.78.90 --port= # 用 = 连接参数值
  12. The server host is: 10.123.78.90, the server port is:
  13. ./gflags_test --help # 用 help 查看可指定的参数及参数说明
  14. gflags_test: Warning: SetUsageMessage() never called
  15. Flags from /home/rookie/code/gflags/src/gflags.cc:
  16. .... # 略
  17.  
  18. Flags from /home/rookie/code/gflags/src/gflags_reporting.cc:
  19. ..... # 略
  20.  
  21. Flags from gflags_test.cc: #这里是我们定义的参数说明和默认值
  22. -host (the server host) type: string default: "127.0.0.1"
  23. -port (the server port) type: int32 default:

在上面我们使用了两种类型的参数,string 和 int32,gflags 一共支持 5 种类型的命令行参数定义:

  • DEFINE_bool: 布尔类型
  • DEFINE_int32: 32 位整数
  • DEFINE_int64: 64 位整数
  • DEFINE_uint64: 无符号 64 位整数
  • DEFINE_double: 浮点类型 double
  • DEFINE_string: C++ string 类型

如果你希望支持更复杂的结构,比如 list,你需要通过自己做一定的定义和解析,比如字符串按某个分隔符分割得到一个列表。

每一种类型的定义和使用都跟上面我们的例子相似,有所不同的是 bool 参数,bool 参数在命令行可以不指定值也可以指定值,假如我们定义了一个 bool 参数 debug_switch,可以在命令行这样指定:

  1. ./gflags_test -debug_switch # 这样就是 true
  2. ./gflags_test -debug_switch=true # 这样也是 true
  3. ./gflags_test -debug_switch= # 这样也是 true
  4. ./gflags_test -debug_switch=false # 也是 false

所有我们定义的 gflags 变量都可以通过 FLAGS_ 前缀加参数名访问,gflags 变量也可以被自由修改:

  1. if (FLAGS_consider_made_up_languages)
  2. FLAGS_languages += ",klingon";
  3. if (FLAGS_languages.find("finnish") != string::npos)
  4. HandleFinnish();

进阶:

定义规范

如果你想要访问在另一个文件定义的 gflags 变量呢?使用 DECLARE_,它的作用就相当于用 extern 声明变量。为了方便的管理变量,我们推荐在 .cc 或者 .cpp 文件中 DEFINE 变量,然后只在对应 .h 中或者单元测试中 DECLARE 变量。例如,在 foo.cc 定义了一个 gflags 变量 DEFINE_string(name, 'bob', ''),假如你需要在其他文件中使用该变量,那么在 foo.h 中声明 DECLARE_string(name),然后在使用该变量的文件中 include "foo.h" 就可以。当然,这只是为了更好地管理文件关联,如果你不想遵循也是可以的。

参数检查

如果你定义的 gflags 参数很重要,希望检查其值是否符合预期,那么可以定义并注册参数的值的检查函数。如果采用 static 全局变量来确保检查函数会在 main 开始时被注册,可以保证注册会在 ParseCommandLineFlags 函数之前。如果默认值检查失败,那么 ParseCommandLineFlags 将会使程序退出。如果之后使用 SetCommandLineOption() 来改变参数的值,那么检查函数也会被调用,但是如果验证失败,只会返回 false,然后参数保持原来的值,程序不会结束。看下面的程序示例:

  1. #include <stdint.h>// 定义了 int16_t 、 uint32_t 、 int64_t 等整型,在需要确定大小的整型时可以使用它们代替 short 、 unsigned long long 等,在 C 整型中,只使用 int 。适当情况下,推 荐使用标准类型如 size_t 和 ptrdiff_t
  2. #include <stdio.h>
  3. #include <iostream>
  4. #include <gflags/gflags.h>
  5.  
  6. //定义对FLAGS_port的检查函数
  7. static bool ValidatePort(const char* name, int32_t value)
  8. {
  9. if(value > && value < )
  10. return true;
  11. printf("Invalid value for --%s: %d\n",name, (int)value);
  12. return false;
  13. }
  14.  
  15. /**
  16. * 设置命令行参数变量
  17. * 默认的主机地址为 127.0.0.1,变量解释为 'the server host'
  18. * 默认的端口为 12306,变量解释为 'the server port'
  19. */
  20. DEFINE_string(host, "127.0.0.1", "the server host");
  21. DEFINE_int32(port, , "the server port");
  22.  
  23. //使用全局static变量来注册函数,static变量会在main函数开始时就调用
  24.  
  25. static const bool port_dummy = gflags::RegisterFlagValidator(&FLAGS_port, &ValidatePort);
  26.  
  27. int main(int argc, char** argv)
  28. {
  29. //解析命令行参数,一般都放在main函数中开始位置
  30. gflags::ParseCommandLineFlags(&argc, &argv, true);
  31. std::cout << "The server host is: " << FLAGS_host
  32. << ", the server port is: " <<FLAGS_port << std::endl;
  33.  
  34. //使用SetCommandLineOPtion函数对参数进行设置才会调用检查函数
  35. gflags::SetCommandLineOption("port", "-2");
  36. std::cout << "The server host is: " << FLAGS_host
  37. << ", the server port is: " <<FLAGS_port << std::endl;
  38. return ;
  39. }

运行:

  1. #命令行指定非法值,程序解析参数时直接退出
  2. ./gflags_test -port -
  3. Invalid value for --port: -
  4. ERROR: failed validation of new value '-2' for flag 'port'
  5. # 这里参数默认值合法,但是 SetCommandLineOption 指定的值不合法,程序不退出,参数保持原来的值
  6. ./gflags_test
  7. The server host is: 127.0.0.1, the server port is:
  8. Invalid value for --port: -
  9. The server host is: 127.0.0.1, the server port is:

使用flagfile

如果我们定义了很多参数,那么每次启动时都在命令行指定对应的参数显然是不合理的。gflags 库已经很好的解决了这个问题。你可以把 flag 参数和对应的值写在文件中,然后运行时使用 -flagfile 来指定对应的 flag 文件就好。文件中的参数定义格式与通过命令行指定是一样的。

例如

我们可以定义这样一个文件,文件后缀名没有关系,为了方便管理可以使用 server.flags:

  1. --host=10.123.14.11
  2. --port=

然后执行

  1. ./gflags_test --flagfile server.flags
  2. The server host is: 10.123.14.11, the server port is:

结合到cartographer_ros里面的

  1. roslaunch cartographer_ros demo_revo_lds.launch bag_filename:=/home/gary/cartographer_ws/bagfiles/Revo_LDS/cartographer_paper_revo_lds.bag

在node_main.cc文件里面的

DEFINE_string(configuration_directory, "",
              "First directory in which configuration files are searched, "
              "second is always the Cartographer installation to allow "
              "including files from there.");
DEFINE_string(configuration_basename, "",
              "Basename, i.e. not containing any directory prefix, of the "
              "configuration file.");

  1. CHECK(!FLAGS_configuration_directory.empty())
    << "-configuration_directory is missing.";
    CHECK(!FLAGS_configuration_basename.empty())
    << "-configuration_basename is missing.";

在launch 文件里面可以看到有如下

<node name="cartographer_node" pkg="cartographer_ros"
      type="cartographer_node" args="
          -configuration_directory $(find cartographer_ros)/configuration_files
          -configuration_basename revo_lds.lua"
      output="screen">
    <remap from="scan" to="horizontal_laser_2d" />
  </node>

how to use gflags的更多相关文章

  1. gflags

    一.安装配置 下载地址: https://code.google.com/p/gflags/downloads/list 解压安装: tar zxvf gflags-2.0.tar.gz && ...

  2. 使用PageHeap.EXE或GFlags.EXE检查内存越界错误 (转)

    2011-05-27 20:19 290人阅读 评论(0) 收藏 举报 microsoftdebuggingstructureoutputimagefile 必先利其器之一:使用PageHeap.EX ...

  3. google gflags使用.

    code.google.com 被墙的好开心... gflags很简单. 编译使用都很简单. (不像omaha这种丧心病狂的编译依赖). cmake 生成一下. 一路顺风顺水. 值得注意的是:  默认 ...

  4. 使用PageHeap.EXE或GFlags.EXE检查内存越界错误

    必先利其器之一:使用PageHeap.EXE或GFlags.EXE检查内存越界错误 Article last modified on 2002-6-3 ------------------------ ...

  5. Windbg的gflags.exe -- Attach调试利器

    有没有碰到过程序启动就因为异常直接crash?有没有碰到程序启动之后什么反应也没有?有没有碰到过程序启动之后去触发另一个进程失败?有没有碰到别人的程序调用了你的代码,出现问题以后,让你来调查,而你只有 ...

  6. gflags 学习

    一.下载 https://github.com/gflags/gflags 二.可以将gflags编译成lib 三.在需要的工程的workspace下面引入编译好的gflags动态库,在库里面写好BU ...

  7. linux下gflags的安装

    gflags是google开发的一套命令行参数解析工具,被很多软件系统所依赖,应该算是一个基础的库,安装其实很简单,但是如果在网上找的一些教程大部分都是安装后不能被其他软件调用的,因为默认使用cmak ...

  8. gflags命令行参数解析

    gflags库是google开源的命令行参数解析工具. 安装 官方没有提供二进制库,但是Debian/Ubuntu平台本身提供了二进制库,可以直接git clone https://github.co ...

  9. Gflags 简明使用

    简介 Google 的 gflags 是一套命令行参数处理的开源库.比 getopt 更方便,更功能强大,从 C++的库更好的支持 C++(如 C++的 string 类型).包括 C++的版本和 p ...

  10. Windows下使用Gflags和UMDH查找内存泄漏

    GFlags和UMDH与WinDbg一样,都是Debugging Tools for Windows里的工具. 1.设置符号路径 去微软官网下载对应的操作系统的符号安装文件,并安装到某个目录,如C:\ ...

随机推荐

  1. webRTC脱坑笔记(三)— webRTC API之RTCPeerConnection

    RTCPeerConnection API是每个浏览器之间点对点连接的核心,RTCPeerConnection是WebRTC组件,用于处理对等体之间流数据的稳定和有效通信. RTCPeerConnec ...

  2. spark大数据快速分析第二章

    1.驱动程序通过一个SparkContext对象来访问Spark,此对象代表对计算集群的一个连接.shell已经自动创建了一个SparkContext对象.利用SparkContext对象来创建一个R ...

  3. String、StringBuffer、StringBuilder详解

    String类 字符串广泛应用在java编程中,String类在java.lang包中,String类是final修饰的,不能被继承,String类对象创建后不能修改,由0或多个字符组成,包含在一对双 ...

  4. 箭头函数以及this指向问题

    一.定义函数的方式 //1.function const aaa = function () { } //2.对象字面量中定义函数 const obj = { bbb() { } } //3.ES6中 ...

  5. 【JVM】吞吐量与延迟关系

    堆内存增大,gc一次能处理的数量变大,吞吐量大:但是gc一次的时间会变长,导致后面排队的线程等待时间变长: 向反,如果堆内存小,gc一次时间短,排队等待的线程等待时间变短,延迟减少,但一次请求的数量变 ...

  6. 本地develop往远端develop上推代码步骤

  7. java-设计原则

    七大设计原则 单一职责原则: 尽可能的功能细分(类细分,方法细分):如一个类由于某变量而细分方法,该细分方法再细分,需要重构(最好细分类) 接口隔离原则:(C类实现A接口全部方法,而D,B类依赖于A接 ...

  8. spring依赖搜索

    spring项目在启动时,spring框架会根据名称自动搜索实现类. 这在日常开发中还是很有用的. 下面举两个例子. 1. 先写一个接口(或者抽象类) public interface IPerson ...

  9. 双十一高并发场景背后的数据库RDS技术揭秘

    [战报]11月11日聚石塔(阿里云数据库RDS产品形态)峰值QPS突破X00w,Proxy 峰值QPS超过X00w. 双十一就要来了,全世界都为其疯狂,但是在双十一抢购中经常会出现几万人抢一个红包或者 ...

  10. 八、条件变量std::condition_variable、wait()、notify_one()、notify_all(粗略)

    一.std::condition_variable 用在多线程中. 线程A:等待一个条件满足 线程B:专门在消息队列中扔消息,线程B触发了这个条件,A就满足条件了,可以继续执行 std::condit ...