【C++】google gflags库

介绍

  • gflagsgoogle的一个开源的处理命令行参数的库,使用c++开发,具备python接口,可以替代getopt
  • gflags使用起来比getopt方便,但是不支持参数的简写(例如getopt支持--list缩写成-lgflags不支持)。

安装

暂留(TODO)

基础使用

  1. 需要引用头文件#include
  2. 在使用命令行参数的文件文件中(源文件或头文件),首先使用一下定义语句进行变量的定义:

    DEFINE_int32
    DEFINE_int64
    DEFINE_uint64
    DEFINE_bool
    DEFINE_double
    DEFINE_string

    定义的语句的使用方法:
    DEFINE_int32(name, default_value, "description");

  3. 在main函数中加入:(一般是放在main函数的头几行,越早了解用户的需求越好)
    google::ParseCommandLineFlags(&argc, &argv, true);
    argcargv想必大家都很清楚了,说明以下第三个参数的作用:
    如果设为true,则该函数处理完成后,argv中只保留argv[0],argc会被设置为1。
    如果为false,则argvargc会被保留,但是注意函数会调整argv中的顺序。

  4. 这样,在后续代码中可以使用FLAGS_变量名访问对应的命令行参数了
    printf("%s", FLAGS_name);

  5. 最后,编译成可执行文件之后,用户可以使用:executable --参数1=值1 --参数2=值2 ...来为这些命令行参数赋值。
    例如:./mycmd --var1="test" --var2=3.141592654 --var3=32767 --mybool1=true --mybool2 --nomybool3
    这里值得注意的是bool类型命令行参数,除了可以使用--xxx=true/false之外,还可以使用--xxx--noxxx后面不加等号的方式指定truefalse

  6. 同时也可以将参数配置到一个文件中例如gflag.conf,可以直接使用配置文件传递参数
    ./mycmd --flagfile=gflag.conf

举个栗子来说明一下

#include 
#include 
#include 

DEFINE_string(name,"name_null","name");
DEFINE_int32(age,0,"");
DEFINE_string(school,"none","");
DEFINE_string(sex,"none","");
DEFINE_bool(marriage,true,"");

int main(int argc, char** argv)
{
    google::ParseCommandLineFlags(&argc, &argv, true);
    std::cout << "my name is :" << FLAGS_name << std::endl
              << "my age is :" << FLAGS_age << std::endl
              << "my school is :" << FLAGS_school << std::endl;

    return 0;
}

编译后生成test_gflags可执行程序.

  • 运行./test_gflags --name=fang,结果如下
my name is :fang
my age is :0
my school is :none
  • 写配置文件gflag_conf.conf
--name=frank
--age=25
--sex=man
--school=pku
--marriage=false

运行./test_gflags --flagfile=gflag_conf.conf,结果如下:

my name is :frank
my age is :25
my school is :pku
  • 如果修改配置文件为
--name= frank
--age=25
--sex=man
--school=pku
--marriage=false

会得出一样的结论,证明--name=frank这里的等于号后面可以接空格

  • 如果修改配置文件为
--name =frank
--age=25
--sex=man
--school=pku
--marriage=false

结果中name的值变为默认值,说明等于号前面不能是空格。

结论--name=frank这里的等于号后面可以接空格,但是前面不能,不会报错,但是会使用默认值。

  • 同时使用配置文件和传入参数
[[email protected] 003_learn_gflags]$ ./test_gflags --flagfile=gflag_conf.conf --name=fang
my name is :fang
my age is :25
my school is :pku

[[email protected] 003_learn_gflags]$ ./test_gflags --name=fang --flagfile=gflag_conf.conf            
my name is :frank
my age is :25
my school is :pku

[[email protected] 003_learn_gflags]$ ./test_gflags --name=fang --flagfile=gflag_conf.conf --name=jin
my name is :jin
my age is :25
my school is :pku

可见跟参数传入的顺序有关系,或者说是可以被覆盖的。建议使用配置文件的方式,更加方便。

进阶使用

  1. 在其他文件中使用定义的flags变量:有些时候需要在main之外的文件使用定义的flags变量,这时候可以使用宏定义DECLARE_xxx(变量名)声明一下(就和c++中全局变量的使用是一样的,extern一下一样)

    DECLARE_bool: boolean
    DECLARE_int32: 32-bit integer
    DECLARE_int64: 64-bit integer
    DECLARE_uint64: unsigned 64-bit integer
    DECLARE_double: double
    DECLARE_string: C++ string

    gflagsdoc中,推荐在对应的.h文件中进行DECLARE_xxx声明,需要使用的文件直接include就行了。

  2. 检验输入参数是否合法:gflags库支持定制自己的输入参数检查的函数,如下:

    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");
    static const bool port_dummy = RegisterFlagValidator(&FLAGS_port, &ValidatePort);
  3. 判断flags变量是否被用户使用:在gflags.h中,还定义了一些平常用不到的函数和结构体。这里举一个例子,判断参数port有没有被用户设定过

    google::CommandLineFlagInfo info;
     if(GetCommandLineFlagInfo("port" ,&info) && info.is_default) {
         FLAGS_port = 27015;
     }
  4. 定制你自己的help信息与version信息:(gflags里面已经定义了-h--version,你可以通过以下方式定制它们的内容)

    • version信息:使用google::SetVersionString设定,使用google::VersionString访问
    • help信息:使用google::SetUsageMessage设定,使用google::ProgramUsage访问

    注意google::SetUsageMessagegoogle::SetVersionString必须在google::ParseCommandLineFlags之前执行

  5. 特殊参数

    • --help 打印定义过的所有参数的帮助信息
      +--version 打印版本信息 通过google::SetVersionString()指定
    • --nodefok 但命令行中出现没有定义的参数时,并不退出(error-exit)
    • --fromenv 从环境变量读取参数值 --fromenv=foo,bar表明要从环境变量读取foo,bar两个参数的值。通过export FLAGS_foo=xxx; export FLAGS_bar=yyy程序就可读到foo,bar的值分别为xxx,yyy
    • --tryfromenv--fromenv类似,当参数的没有在环境变量定义时,不退出(fatal-exit)
    • --flagfile 从文件读取参数值,--flagfile=my.conf表明要从my.conf文件读取参数的值。在配置文件中指定参数值与在命令行方式类似,另外在flagfile里可进一步通过--flagfile来包含其他的文件。

参考自 http://blog.csdn.net/lezardfu/article/details/23753741

你可能感兴趣的:(C++/C)