gflags使用详解

简介

gflags是什么?gflags是google开源的命令行标记处理库;
那么什么是命令行标记呢?顾名思义就是当运行一个可执行文件时,由用户为其指定的标记,形如:

 fgrep -l -f ./test ccc jjj

注意上述命令,-l与-f ./test是命令行标记,而ccc与jjj是命令行参数,因为这两者不是以破折号开头的。

一般的一个可执行文件,允许用户为其传入命令行标记以及参数,如上述例子,-l是一个不带参数的标记,-f是一个带了参数“./test”的标记,而gflags可以解析这些标记以及参数并将其存储在某些数据结构中。

gflags不像getopt()那样,gflags的flags可以分散到各个源文件而不是只在一个地方,也就是说只要是和定义了指定flags的源文件链接的其他文件都可以使用这个flags,这是灵活而又强大的,但这也是危险的,如果两个文件定义的flags一样,那么当它们链接在一起的时候将会出错。

下载与安装(ubuntu环境)

gflags官方github链接,克隆代码:

git clone https://github.com/gflags/gflags.git gflags_stable

安装二进制发布包:

sudo apt-get install libgflags-dev

安装cmake:

sudo apt-get install cmake-curses-gui

cd到代码根目录,即gflags_stable目录,执行如下命令:

mkdir build && cd build
ccmake ..
# 在cmake界面一路按‘c’直到可以按‘g’
make
sudo make install

安装成功后会提示如下信息:

[ 50%] Built target gflags_static
[100%] Built target gflags_nothreads_static
Install the project...
-- Install configuration: "Release"
-- Installing: /usr/local/lib/libgflags.a
-- Installing: /usr/local/lib/libgflags_nothreads.a
-- Installing: /usr/local/include/gflags/gflags.h
-- Installing: /usr/local/include/gflags/gflags_declare.h
-- Installing: /usr/local/include/gflags/gflags_completions.h
-- Installing: /usr/local/include/gflags/gflags_gflags.h
-- Installing: /usr/local/lib/cmake/gflags/gflags-config.cmake
-- Installing: /usr/local/lib/cmake/gflags/gflags-config-version.cmake
-- Installing: /usr/local/lib/cmake/gflags/gflags-targets.cmake
-- Installing: /usr/local/lib/cmake/gflags/gflags-targets-release.cmake
-- Installing: /usr/local/lib/cmake/gflags/gflags-nonamespace-targets.cmake
-- Installing: /usr/local/lib/cmake/gflags/gflags-nonamespace-targets-release.cmake
-- Installing: /usr/local/bin/gflags_completions.sh
-- Installing: /usr/local/lib/pkgconfig/gflags.pc
-- Installing: /home/caojingsong/.cmake/packages/gflags/e5f7ce61772240490d3164df06f58ce9

编译代码时需要连同gflags的静态库一同编译

g++ demo.cpp /usr/local/lib/libgflags.a -lpthread

使用

在程序中定义flag

	#include <gflags/gflags.h> // 头文件必须得加啊啊啊啊啊
	DEFINE_bool(is_handsome, true, "Is the author a handsome guy");
   	DEFINE_string(hobby, "eat, drink, sleep",
                 "comma-separated list of hobby to offer in the 'hobby' menu");

如上,DEFINE有三个宏,其意义分别为:flag的名称,flag的默认值,help字符串。如何查看help信息呢,在执行可执行文件时加上–help选项即可,但是如果要显示help信息,代码里需要调用接口gflags::ParseCommandLineFlags(&argc, &argv, true)才行。

gflags支持的变量类型如下:

  • DEFINE_bool: 布尔类型
  • DEFINE_int32: 32-bit 整型
  • DEFINE_int64: 64-bit 整型
  • DEFINE_uint64: 无符号 64-bit 整型
  • DEFINE_double: double
  • DEFINE_string: C++ string

在程序中使用flag

对于DEFINE过的flag我们可以像使用普通变量那样读写它,只需加一个“FLAGS_”前缀即可,如下:

 if (FLAGS_is_handsome)
     FLAGS_is_handsome = false; 
 std::cout << FLAGS_hobby << std::endl;

在其他文件中使用flag

形如上述例子,我们在一个源文件中使用flag方式是先“DEFINE_”然后“FLAGS_”使用即可,但如果想在其他文件访问这个flag呢?举个例子,我们上述flag定义在hello.cpp,而我们要在bye.cpp中使用它,那么我们只需在bye.cpp中做如下声明:

DECLARE_bool(is_handsome);
DECLARE_string(hobby);

上述DECLARE作用等同于extern.

注册flag验证器

当我们DEFINE一个flag时,可以为其注册一个Validator,如下:

static bool ValidatePort(const char* flagname, int32 value) {
   if (value > 0 && value < 32768)   // value is ok
     return true;
   printf("Invalid value for --%s: %d\n", flagname, (int)value);
   return false;
}
DEFINE_int32(port, 0, "What port to listen on");
DEFINE_validator(port, &ValidatePort);

上述DEFINE_validator宏将会调用RegisterFlagValidator()函数,成功返回true,失败返回false,失败的原因可能为:1、第一个参数不是flag;2、该flag被不同的validator注册。返回值作为全局静态布尔变量是可以被访问的,格式为:

<flag>_validator_registered

设置flag

我们可以通过给可执行文件传输命令行参数来修改flag的默认值,只需要在main函数开头,调用如下函数:

gflags::ParseCommandLineFlags(&argc, &argv, true);

上述参数的最后一个参数是"remove_flag",如果为true该函数将会从argv中移除flag并修改argc为相应的值,如此下来,argv只保留命令行参数,而不再有命令行标记
如果remove_flag为false,那么该函数将会重新排列argv。
具体命令行传参格式如下:

a.out --nois_handsome -hobby="play football" 

当运行ParseCommandLineFlags时,将会设置FLAGS_is_handsome为false,
FLAGS_hobby 为"play football",注意上述布尔类型变量通过在名字前加no将其设置为false。

对于hobby标记还有如下指定方式:

a.out --hobby="play football"
a.out -hobby="play football"
a.out --hobby "play football"
a.out -hobby "play football"

对于布尔变量有下述几种设置方式:

a.out --is_handsome
a.out --nois_handsome
a.out --is_handsome=true
a.out --is_handsome=false

不过为了使自己的程序易于理解可读,
建议非布尔flag使用这种形式:–variable=value
布尔flag使用这种形式:–variable/–novariable

API

gflags提供了一些有用的API如:gflags::SetUsageMessage() 和gflags::SetVersionString更多信息请参考gflags.h头文件

最后一点

出于一些安全原因或者想要减小可执行文件大小,我们可以去掉自己定义的flag的help信息,如下:

#define STRIP_FLAG_HELP 1    // this must go before the #include!
#include <gflags/gflags.h>

参考文献

以上内容均参考自该文章:https://gflags.github.io/gflags/

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值