Gflags是一套命名行处理的开源库,支持C++和Python,这里我主要学习C++上的应用。与getopt相比,Gflags具有更好的灵活性,可以在任意位置定义flags。
定义flag。flag的定义需要使用到gflags.h中的宏。gflags为用户提供了多种可以定义的flags类型,类型如下
宏语句 | flag类型 |
---|---|
DEFINE_string | string字符串类型 |
DEFINE_int32 | 32位整型 |
DEFINE_int64 | 64位整型 |
DEFINE_uint64 | 64位无符号整型 |
DEFINE_double | 64位双浮点型 |
DEFINE_bool | 布尔类型 |
以string类型为例,一个完整的定义语句共包括三部分,分别是flag的名称,默认值和说明,其中说明是在用户使用–help时的描述内容。
需要注意的是,由于名称对应的是变量名,因此不用加双引号,而默认值与说明均为一段字符串,因此都要加双引号。
DEFINE_string(name, "minminwang", "please input your name")
flag的布局。一个flag只可以被定义一次,如果想要在其他文件中使用已经定义的flag,需要使用到另一个宏DECLARE。每一种类型的flag都有一个对应的DECLARE宏。
为了降低文件之间的相互依赖,Gflags的使用一般需要在一个.c文件中使用DEFINE宏定义相关的flag,然后在.h文件中使用DECLARE宏进行声明,这样每个include这一.h文件的地方都可以使用全部的flag。
DECLARE_string(name)
flag变量。每声明一个flag时都会生成一个与之对应的flag变量,可以直接通过FLAG_flag_name的方式来获取改变量,变量类型取决于声明时所使用的宏类型,可以像正常变量一样对其进行操作。例如通过上述语句,我们就得到了一个名为FLAG_name的flag变量。在其他文件中,使用DECLARE宏之后就可以使用该flag变量。DECLARE语句等效于extern FLAG_name但这样会形成一种隐式的依赖关系,不推荐使用。
flag验证器。Gflags允许为每个flag注册一个验证器,可以在每次获取flag值之后对其格式或内容就行校验。验证器的注册格式为DEFINE_validator(flag名称,&验证函数)。一个简单的验证月份的验证器的注册方式如下:
static bool validateMonth(const char* flagname, int32 month){
if (month >= 1 && month <= 12) {
return true;
} else {
printf("%d is not a %s!\n", (int)month, flagname);
return false;
}
}
DEFINE_int32(month, 1, "a month in a year");
DEFINE_validator(month, &validateMonth);
flag参数的初始化。在flag参数定义完成之后,需要在main函数中通过命令行的输入对其进行初始化,具体可以使用google:ParseCommandLineFlags函数完成。该函数的输入共有三个,分别为argc,argv和remove_flags。其中argc与argv均为main函数的输入值,对应的是命令行的输入,由于在google::ParseCommandLineFlags函数中需要对这些参数进行修改,因此使用指针传递。remove_flags是一个bool类型的变量,当remove_flags为true时,ParseCommandLineFlags函数会在argv中移除标识与参数,只保留命名行参数,并将argc的值相应减小;而当其值为false时,ParseCommandLineFlags会在argv中保留参数和标识,只是将其移动到命令行参数的前面,同时argc不变。
./sample.sh --name="minminwang" --age=18 "daydayup" // --name和--age均为标识,minminwang和18为对应的参数,daydayup为命令行参数。
static bool validateAge(const char* flagname, int32 age){
if (age >=0 && age<=100) {
return ture;
} else {
printf("Invalid %s: %d", flagname, (int)age);
return false;
}
}
DEFINE_stirng(name, "", "the name of user.");
DEFINE_int32(age, 0, "the age of user.");
DEFINE_validator(age, &vallidateAge);
main(int argc, char* argv){ // 此时argc=3,argv="--name=minminwang --age=18 daydayup"
google::ParseCommandLineFlags(&argc, &argv, true); // 之后argc=1, argv="daydayup"
}
通过命令行设置flag的值。
// 对于bool类型的flag共有四种方式
--sex
--sex=true
--nosex
--sex=false
// 对于其他类型的flag也有四种方式
--name="minminwang"
-name="minminwang"
--name "minminwang"
-name "minminwang"
特殊标识。
--help 显示文件中所有标识的完整帮助信息
--helpfull 和-help 一样,
--helpshort 只显示当前执行文件里的标志
--helpxml 以 xml 凡是打印,方便处理
--version 打印版本信息,由 google::SetVersionString()设定
--flagfile -flagfile=f 从文件 f 中读取命令行参数
...
#include
DEFINE_bool(big_menu, true, "Include 'advanced' options in the menu listing");
DEFINE_string(languages, "english,french,german", "comma-separated list of languages to offer in the 'lang' menu");
int main(int argc, char **argv) {
google::ParseCommandLineFlags(&argc, &argv, true);
cout << "argc=" << argc << endl;
if (FLAGS_big_menu) {
cout << "big menu is ture" << endl;
} else {
cout << "big menu is flase" << endl;
}
cout << "languages=" << FLAGS_languages << endl;
return 0;
}