google gflag使用指南

google gflags使用指南

 

google gflags是google使用的一个开源库,用于解析命令行标记。目前的gflags有C++和Python两个版本。本文主要介绍gflags的C++版本使用方法。

命令行标记是指用户在运行可执行程序时,在命令行中指定的参数。例如,对于命令:

 

fgrep -l -f /var/tmp/foo johannes brahms

 

-l-f /var/tmp/foo是两个命令行标记,而johnnesbrahms则是命令行参数。一个应用往往具有许多个命令行标记,对应这些标记,可以传入一些由用户指定的参数。例如,在上面的例子中,-l标记没有任何参数,而-f标记的参数则是/var/tmp/foo

 

这些标记和参数存储在main函数的argcargv参数中。一般而言,main函数总有如下的形式:

 

int main(int argc, char ** argv) {…}


 

 

其中argc指明了argv数组的长度,而argv数组则空格为分割,存储命令行后用户输入的参数。在GNU C Library中,这个工作主要是由getopt函数来完成的。以下是getopt函数的一个例子:

 

    #include <ctype.h>

     #include <stdio.h>

     #include <stdlib.h>

     #include <unistd.h>

     

     int

     main (int argc, char **argv)

     {

       int aflag = 0;

       int bflag = 0;

       char *cvalue = NULL;

       int index;

       int c;

     

       opterr = 0;

     

       while ((c = getopt (argc, argv, "abc:")) != -1)

         switch (c)

           {

           case 'a':

             aflag = 1;

             break;

           case 'b':

             bflag = 1;

             break;

           case 'c':

             cvalue = optarg;

             break;

           case '?':

             if (optopt == 'c')

               fprintf (stderr, "Option -%c requires an argument.\n", optopt);

             else if (isprint (optopt))

               fprintf (stderr, "Unknown option `-%c'.\n", optopt);

             else

               fprintf (stderr,

                        "Unknown option character `\\x%x'.\n",

                        optopt);

             return 1;

           default:

             abort ();

           }

     

       printf ("aflag = %d, bflag = %d, cvalue = %s\n",

               aflag, bflag, cvalue);

     

       for (index = optind; index < argc; index++)

         printf ("Non-option argument %s\n", argv[index]);

       return 0;

     }

 


 在这个例子中可以看出,所有的标记的定义都必须要集中在一个地方处理(也就是switch代码段中)。而gflags则与getopt函数不同,在gflags中,标记的定义分散在源代码中,不需要列举在一个地方。这意味着单个的源代码文件可以定义他们自己所使用的标记,一切连接到这个文件的应用将获取这个标记,并且gflags将自动对这个标记进行适当的处理。这对于软件的灵活性及代码的重用是很有好处的。当然,这也产生了一定的风险,特别是,两个不同的文件可能会定义拥有同一个名字的命令行标记,在平常的情况下没有问题,但当这两个文件被同一个二进制程序连接的时候,就会出现错误。

gflags使用C++语言实现,其风格也是C++风格的。本文的其余部分介绍了如何使用gflags。

一、如何定义一个命令行标记

使用gflags需要引用gflags头文件:

 

#include <gflags/gflags.h>

 

在gflags.h文件的结尾,定义了一些标记定义宏,因此在引用了gflags.h后,定义一个命令行标记就变得十分简单了。如,在foo.cc文件的开头,我们引入如下的命令行标记的定义:

#include <gflags/gflags.h>

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

 

在这段代码中,我们定义了两个命令行标记:bool型的big_menu,以及string型的language。所有的DEFINE宏都有三个参数:标记的名字,默认值,以及针对这个标记的说明。第三个参数是非常有用的,尤其是在构建大型程序的时候,在命令行中使用—help标记可以列出被gflags所定义的所有标记的类型、默认值及对其的说明(也就是宏第三个参数)。

DEFINE宏支持的类型包括:

o    DEFINE_bool: boolean

o    DEFINE_int32: 32-bit integer

o    DEFINE_int64: 64-bit integer

o    DEFINE_uint64: unsigned 64-bit integer

o    DEFINE_double: double

o    DEFINE_string: C++ string

可以在可执行程序的任何一个源文件中定义一个标记,而针对每个标记,只需要定义一次。如果想要在不同的源文件中访问该标记,可以使用DECLARE宏来声明这个标记(其实就是声明了一个extern变量的引用)。一个更好的方法是,对于一个标记,可以在foo.cc中定义它,并且在foo.h中声明它。这样,包含了foo.h的所有源文件都可以引用这个标记。

二、如何访问一个标记

访问标记较为简单。只要对标记进行了定义或者声明,那么只需要在使用它的地方加上前缀“FLAGS_”就可以引用这个标记了。如,

if (FLAGS_consider_made_up_languages)

FLAGS_languages += ",klingon";   // implied by --consider_made_up_language

if (FLAGS_languages.find("finnish") != string::npos)
     HandleFinnish();


 

三、在命令行中使用标记

对于上面的foo.cc和foo.h,如果其编译后产生的二进制文件为app_containing_foo,则在命令行中设置这些标记的方法为:

 

app_containing_foo --nobig_menu -languages="chinese,japanese,korean" …

 

这个命令会把big_menu设置为false,并且将language设置为“chinese,japanese,Korean”。对于string、int、double等类型的标记,设置标记时使用如下形式:

 

o    app_containing_foo --languages="chinese,japanese,korean"

o    app_containing_foo -languages="chinese,japanese,korean"

o    app_containing_foo --languages "chinese,japanese,korean"

o    app_containing_foo -languages "chinese,japanese,korean"

 

这些方式是等价的。但注意gflags不支持短标记与合并标记。如ls –la这种类型,是不能够被gflags处理的。这和getopt函数有所不同。

 需要注意的还有以下几点:

1,--连用会终止标记。如命令:foo -f1 1 -- -f2 2,则f2标记将不被处理;

2,bool型的标记,如big_menu,既可以使用—big_menu=true/false,也可以使用—big_menu/--nobig_menu这种方式。gflags都可以解析。

3,使用未被定义的标记将引发严重错误。

四、在程序中解析标记

在程序中解析标记可以使用如下函数:

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

 

注意argc和argv均以地址方式传递,也就是该函数可以改变argc和argv的内容。通常这段代码会出现在main函数的开始。最后一个参数是移除标记,它指明了是否将被gflags成功解析的标记从参数列表中移除。例如,对于命令行:

foo –options=start file1 file2

在这个命令行中,options是一个命令行标记,将被gflags解析(如果它已经被定义了);而file1和file2则是命令行参数。如果设置remove标记位ture,则—options=start会在调用ParseCommandLineFlags后被移除,此时argc=2,而argv中则保存了file1和file2两个参数。如果remove标记位设为false,则—options=start将不会被移除,则argc不会改变,但argv会重新排列,将所有的标记排列在前面。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值