谷歌命令行解析工具gflags的使用
Gflags简介
GFlags是Google开源的一套命令行参数处理的开源库。
在一个源码文件定义的flag,链接了该文件的应用就可以使用该flag,可以方便的复用代码。
如果不同的文件定义了相同的flag,链接时会报错。
可参考下面链接进行安装
https://github.com/gflags/gflags/blob/master/INSTALL.md
github.com/gflags/gflags/blob/master/INSTALL.md
使用
举例说明
#include <gflags/gflags.h>
#include <iostream>
#include <string>
using namespace std;
DEFINE_string(parameter1, "para1", "the first parameter.");
DEFINE_int32(parameter2, 1, "the second parameter.");
int main(int argc, char** argv) {
google::ParseCommandLineFlags(&argc, &argv, true);
cout << "parameter1 = " << FLAGS_parameter1 << endl;
cout << "parameter2 = " << FLAGS_parameter2 << endl;
return 0;
}
1.参数解析
main()函数的参数信息保存在argc, argv中,需要遍历解析,为了处理方便,参数的顺序还会有明确的要求。使用gfalgs可以省略解析部分代码,通过调用ParseCommandLineFlags()就可以完成参数的解析。
int main(int argc, char** argv){...}
使用gflags定义flag,只需要使用相应类型对应的宏定义(在gflags/gflags.h中)就可以,使用flags需要包含头文件 :
#include <gflags/gflags.h>
gflags是如何解析参数的?
程序中需要定义参数名,让程序知道需要识别哪些参数。 如定义一个parameter1参数:
DEFINE_string(parameter1, "para1", "the first parameter.");
该DEFINE_string方法有三个参数:参数名、默认值 、提示性说明
在执行命令时,需要指定参数格式,比如: --parameter1=“outputdir”
调用ParseCommandLineFlags()完成解析,para1参数值将保存在全局变量FLAGS_para1中。
2.参数的定义
gflags支持的类型定义方法:
这些参数使用gflags提供的宏:DEFINE_xxx(变量名,默认值,help_string)。这些变量需要在全局范围内定义。
变量支持以下类型:
方法名 类型
DEFINE_bool: boolean
DEFINE_int32: 32-bit integer
DEFINE_int64: 64-bit integer
DEFINE_uint64: unsigned 64-bit integer
DEFINE_double: double
DEFINE_string: C++ string
在flag中定义简单类型的变量,对于复杂的变量需要用专门的解析工具来进行解析,不要放在flag中进行定义和解析。在一个文件中对某个flag定义后,不可以在不同的文件再定义相同的flag,如果想在其他文件使用该flag,可以通过使用DECLARE宏来进行声明,通常在.cc文件中给出flag的定义,在.h文件中进行DECLARE声明,任何#include .h文件后都可以使用该flag。
用DEFINE宏定义的flag可以像普通的变量一样进行调用,定义的变量是以FLAGS_为前缀,可以像普通的变量一样对其如上述例子中定义的两个变量FLAGS_parameter1和FLAGS_parameter2进行读写。gflag.h头文件给出了具体的get、set函数进行读写。
//该函数的作用是解析命令行参数的,调用应该在main()入口处。
google::ParseCommandLineFlags(&argc, &argv, true);
前两个参数通常户会在main()函数中给出,第三个参数为remove_flags,标识解析后,是否要从参数列表中移除。
true:函数处理完成后,参数信息中将删除gflags相关参数,argv中只保留argv[0],argc会被设置为1。
false:保持argc不变,不删除gflags参数,会调整argv中存储内容的顺序,并且把flag放在命令行参数的前面。
一般参数解析后,也没有保留的必要,可以设置为true。
3.在其他文件中调用flag变量
在另外一个文件中如果想要使用上述定义的para1,只需要在该文件的头部进行如下声明
DECLARE_string(para1);
上述声明从功能上等价于
extern FLAGS_para1;
但是这种extern的声明方式表明了当前文件与flag定义文件之间的依赖关系,这种隐式的依赖关系不利于在大型工程项目中使用,所以官方给出了如下的使用规则:如果在.cc文件中定义了一个flag,要么不进行声明(除了.cc文件中没有其他文件使用该flag),要么只在测试需要用到的文件中或者在.h头文件中进行DECLARE进行声明。
如果其他文件需要使用定义好的flag,就在.h头文件中进行DECLARE声明,然后只需要#include该头文件即可,这样是一种显示的依赖关系,并且该flag成为一个全局变量
4.完整性检查——RegisterFlagValidator
在定义一个flag之后,可以选择定义一个验证器来对该flag进行校验。
每当利用 SetCommandLineOption()函数更改flag的值得时候,都会利用该验证器对flag的值进行合理性验证,当值是合理的时候,验证器会返回true;当值是不合理的时候,验证器会返回false并报错。
本文主要是参考下面三篇网友的博客而写,下面三篇文章写的比较详细,小伙伴们可以点击阅读。
参考博客链接:
https://zhuanlan.zhihu.com/p/95889124?ivk_sa=1024320u
https://blog.csdn.net/red98/article/details/103727063
https://www.jianshu.com/p/2179938a818d