天天看点

how to use gflags

安装:

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

使用:

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

编译运行:

CMakeLists.txt

cmake . &amp;&amp; make

在上面我们使用了两种类型的参数,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,可以在命令行这样指定:

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

进阶:

定义规范

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

参数检查

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

运行:

使用flagfile

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

例如

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

然后执行

结合到cartographer_ros里面的

在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.");

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

  &lt;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"&gt;

    &lt;remap from="scan" to="horizontal_laser_2d" /&gt;

  &lt;/node&gt;