简单介绍

gflags 是 google 开源的用于处理命令行参数的项目。

安装编译

项目主页:gflags

➜  ~  git clone https://github.com/gflags/gflags.git # 下载源码
➜ ~ cd gflags
➜ gflags git:(master) ✗ mkdir build && cd build # 建立文件夹
➜ build git:(master) ✗ cmake .. # 使用 cmake 编译生成 Makefile 文件
➜ build git:(master) ✗ make # make 编译
➜ build git:(master) ✗ sudo make install # 安装库

这时 gflags 库会默认安装在 /usr/local/lib/ 下,头文件放在 /usr/local/include/gflags/ 中。

基础使用

我们从一个简单的需求来看 gflags 的使用,只要一分钟。假如我们有个程序,需要知道服务器的 ip 和端口,我们在程序中有默认的指定参数,同时希望可以通过命令行来指定不同的值。

实现如下:

#include <iostream>

#include <gflags/gflags.h>

/**
* 定义命令行参数变量
* 默认的主机地址为 127.0.0.1,变量解释为 'the server host'
* 默认的端口为 12306,变量解释为 'the server port'
*/
DEFINE_string(host, "127.0.0.1", "the server host");
DEFINE_int32(port, , "the server port"); int main(int argc, char** argv) {
// 解析命令行参数,一般都放在 main 函数中开始位置
gflags::ParseCommandLineFlags(&argc, &argv, true);
// 访问参数变量,加上 FLAGS_
std::cout << "The server host is: " << FLAGS_host
<< ", the server port is: " << FLAGS_port << std::endl;
return ;
}

OK, 写完了让我们编译运行。

➜  test g++ gflags_test.cc -o gflags_test -lgflags -lpthread # -l 链接库进行编译

➜  test ./gflags_test #不带任何参数
The server host is: 127.0.0.1, the server port is: ➜ test ./gflags_test -host 10.123.78.90 #只带 host 参数
The server host is: 10.123.78.90, the server port is: ➜ test ./gflags_test -port # 只带 port 参数
The server host is: 127.0.0.1, the server port is: ➜ test ./gflags_test -host 10.123.78.90 -port # host 和 port 参数
The server host is: 10.123.78.90, the server port is: ➜ test ./gflags_test --host 10.123.78.90 --port # 用 -- 指定
The server host is: 10.123.78.90, the server port is: ➜ test ./gflags_test --host=10.123.78.90 --port= # 用 = 连接参数值
The server host is: 10.123.78.90, the server port is: ➜ test ./gflags_test --help # 用 help 查看可指定的参数及参数说明
gflags_test: Warning: SetUsageMessage() never called Flags from /home/rookie/code/gflags/src/gflags.cc:
.... # 略 Flags from /home/rookie/code/gflags/src/gflags_reporting.cc:
..... # 略 Flags from gflags_test.cc: #这里是我们定义的参数说明和默认值
-host (the server host) type: string default: "127.0.0.1"
-port (the server port) type: int32 default:

看,我们不仅快速完成了需求,而且似乎多了很多看起来不错的特性。在上面我们使用了两种类型的参数,string 和 int32,gflags 一共支持 5 种类型的命令行参数定义:

  • DEFINE_bool: 布尔类型
  • DEFINE_int32: 32 位整数
  • DEFINE_int64: 64 位整数
  • DEFINE_uint64: 无符号 64 位整数
  • DEFINE_double: 浮点类型 double
  • DEFINE_string: C++ string 类型

如果你希望支持更复杂的结构,比如 list,你需要通过自己做一定的定义和解析,比如字符串按某个分隔符分割得到一个列表。

每一种类型的定义和使用都跟上面我们的例子相似,有所不同的是 bool 参数,bool 参数在命令行可以不指定值也可以指定值,假如我们定义了一个 bool 参数 debug_switch,可以在命令行这样指定:

➜  test ./gflags_test -debug_switch  # 这样就是 true
➜ test ./gflags_test -debug_switch=true # 这样也是 true
➜ test ./gflags_test -debug_switch= # 这样也是 true
➜ test ./gflags_test -debug_switch=false # 也是 false

所有我们定义的 gflags 变量都可以通过 FLAGS_ 前缀加参数名访问,gflags 变量也可以被自由修改:

if (FLAGS_consider_made_up_languages)
FLAGS_languages += ",klingon";
if (FLAGS_languages.find("finnish") != string::npos)
HandleFinnish();

进阶?同样 Easy

定义规范

如果你想要访问在另一个文件定义的 gflags 变量呢?使用 DECLARE_,它的作用就相当于用 extern 声明变量。为了方便的管理变量,我们推荐在 .cc 或者 .cpp 文件中 DEFINE 变量,然后只在对应 .h 中或者单元测试中 DECLARE 变量。例如,在 foo.cc 定义了一个 gflags 变量 DEFINE_string(name, 'bob', ''),假如你需要在其他文件中使用该变量,那么在 foo.h 中声明 DECLARE_string(name),然后在使用该变量的文件中 include "foo.h" 就可以。当然,这只是为了更好地管理文件关联,如果你不想遵循也是可以的。

参数检查

如果你定义的 gflags 参数很重要,希望检查其值是否符合预期,那么可以定义并注册参数的值的检查函数。如果采用 static 全局变量来确保检查函数会在 main 开始时被注册,可以保证注册会在 ParseCommandLineFlags 函数之前。如果默认值检查失败,那么 ParseCommandLineFlags 将会使程序退出。如果之后使用 SetCommandLineOption() 来改变参数的值,那么检查函数也会被调用,但是如果验证失败,只会返回 false,然后参数保持原来的值,程序不会结束。看下面的程序示例:

#include <stdint.h>
#include <stdio.h>
#include <iostream> #include <gflags/gflags.h> // 定义对 FLAGS_port 的检查函数
static bool ValidatePort(const char* name, int32_t value) {
if (value > && value < ) {
return true;
}
printf("Invalid value for --%s: %d\n", name, (int)value);
return false;
} /**
* 设置命令行参数变量
* 默认的主机地址为 127.0.0.1,变量解释为 'the server host'
* 默认的端口为 12306,变量解释为 'the server port'
*/
DEFINE_string(host, "127.0.0.1", "the server host");
DEFINE_int32(port, , "the server port"); // 使用全局 static 变量来注册函数,static 变量会在 main 函数开始时就调用
static const bool port_dummy = gflags::RegisterFlagValidator(&FLAGS_port, &ValidatePort); int main(int argc, char** argv) {
// 解析命令行参数,一般都放在 main 函数中开始位置
gflags::ParseCommandLineFlags(&argc, &argv, true);
std::cout << "The server host is: " << FLAGS_host
<< ", the server port is: " << FLAGS_port << std::endl; // 使用 SetCommandLineOption 函数对参数进行设置才会调用检查函数
gflags::SetCommandLineOption("port", "-2");
std::cout << "The server host is: " << FLAGS_host
<< ", the server port is: " << FLAGS_port << std::endl;
return ;
}

让我们运行一下程序,看看怎么样:

#命令行指定非法值,程序解析参数时直接退出
➜ test ./gflags_test -port -
Invalid value for --port: -
ERROR: failed validation of new value '-2' for flag 'port'
# 这里参数默认值合法,但是 SetCommandLineOption 指定的值不合法,程序不退出,参数保持原来的值
➜ test ./gflags_test
The server host is: 127.0.0.1, the server port is:
Invalid value for --port: -
The server host is: 127.0.0.1, the server port is:

使用 flagfile

如果我们定义了很多参数,那么每次启动时都在命令行指定对应的参数显然是不合理的。gflags 库已经很好的解决了这个问题。你可以把 flag 参数和对应的值写在文件中,然后运行时使用 -flagfile 来指定对应的 flag 文件就好。文件中的参数定义格式与通过命令行指定是一样的。

例如,我们可以定义这样一个文件,文件后缀名没有关系,为了方便管理可以使用 .flags:

--host=10.123.14.11
--port=

然后命令行指定:

➜  test ./gflags_test --flagfile server.flags
The server host is: 10.123.14.11, the server port is:

棒!以后再也不用担心参数太多了~^_^

看到这里,是不是觉得 gflags 对你的项目很有帮助?用起来吧,释放超能力 :)

[转]google gflags 库完全使用的更多相关文章

  1. [转]Google gflags使用说明

    gflags是什么: gflags是google的一个开源的处理命令行参数的库,使用c++开发,具备python接口,可以替代getopt. gflags使用起来比getopt方便,但是不支持参数的简 ...

  2. Google 网络库Volley简介

    Volley是什么? 2013 Google I/O 大会发布的Android平台网络通讯库,旨在帮助开发者实现更快速,简单,健壮的网络通讯.支持网络图片的缓存加载功能. 适用场景:数据量不大,但是通 ...

  3. google gflags使用.

    code.google.com 被墙的好开心... gflags很简单. 编译使用都很简单. (不像omaha这种丧心病狂的编译依赖). cmake 生成一下. 一路顺风顺水. 值得注意的是:  默认 ...

  4. Guava 教程2-深入探索 Google Guava 库

    原文出处: oschina 在这个系列的第一部分里,我简单的介绍了非常优秀的Google collections和Guava类库,并简要的解释了作为Java程序员,如果使用Guava库来减少项目中大量 ...

  5. Google序列化库FlatBuffers 1.1发布,及与protobuf的比较

    个人总结: FlatBuffer相对于Protobuffer来讲,优势如下: 1. 由于省去了编解码的过程,所以从速度上快于Protobuffer,个人测试结果100w次编解码,编码上FlatBuff ...

  6. Google开源库-Volley

    Android平台的网络通信库,使是网通信 更快,更简单,更健壮 适合场景: 数据量不大,通信 频繁. 大数据,流媒体是不适合使用的 * 它主要是帮我们载入和缓存从远程网络加载的图片    * 所有的 ...

  7. google base库之simplethread

    // This is the base SimpleThread. You can derive from it and implement the // virtual Run method, or ...

  8. Google Guava 库用法整理<转>

    参考: http://codemunchies.com/2009/10/beautiful-code-with-google-collections-guava-and-static-imports- ...

  9. 文字识别的google的库 tesseract

    https://github.com/tesseract-ocr/tesseract https://github.com/tesseract-ocr/tessdata             字体识 ...

随机推荐

  1. poj 1185(状态压缩DP)

    poj  1185(状态压缩DP) 题意:在一个N*M的矩阵中,‘H'表示不能放大炮,’P'表示可以放大炮,大炮能攻击到沿横向左右各两格,沿纵向上下各两格,现在要放尽可能多的大炮使得,大炮之间不能相互 ...

  2. Memcache服务器端+Redis服务器端+PHP Memcache扩展+PHP Memcached扩展+PHP Redis扩展+MemAdmin Memcache管理工具+一些概念(更新中)

    Memcache和Redis因为操作简单,是我们常用的服务器数据缓存系统,以下文字仅作备忘记录,部份转载至网络. 一.定义 1.Memcache Memcache是一个高性能的分布式的内存对象缓存系统 ...

  3. LINQ to SQL和Entity Framework

    LINQ to SQL和Entity Framework都是一种包含LINQ功能的对象关系映射技术. 那么为什么会有LINQ这个东西的出现呢. 简单来说LINQ是为了满足不知道怎么操作数据库的程序员开 ...

  4. aliyun阿里云alibabaMaven仓库地址——加速你的maven构建

    在maven的settings.xml 文件里 搜索  mirrors   ,把下面内容添加在其子节点内 <mirror> <id>nexus-aliyun</id> ...

  5. 51nod 1218 最长递增子序列 | 思维题

    51nod 1218 最长递增子序列 题面 给出一个序列,求哪些元素可能在某条最长上升子序列中,哪些元素一定在所有最长上升子序列中. 题解 YJY大嫂教导我们,如果以一个元素结尾的LIS长度 + 以它 ...

  6. 【BZOJ3884】上帝与集合的正确用法

    Description 一句话题意,给定\(p\)作为模数: \(p\le 10^7\),数据组数\(T\le1000\). Solution 看到就弃疗了,再见...... 将模数\(p\)拆分成\ ...

  7. BZOJ2876 [Noi2012]骑行川藏 【拉格朗日乘数法】

    题目链接 BZOJ 题解 拉格朗日乘数法 拉格朗日乘数法用以求多元函数在约束下的极值 我们设多元函数\(f(x_1,x_2,x_3,\dots,x_n)\) 以及限制\(g(x_1,x_2,x_3,\ ...

  8. ELK5.4安装Xpack

    X-Pack是一个Elastic Stack的扩展,将安全,警报,监控,报告和图形功能包含在一个易于安装的软件包中.在Elasticsearch 5.0.0之前,必须安装单独的Shield.Watch ...

  9. java 批量文件后缀重命名

    import java.io.File; public class BatchFileSuffixRename { public static void main(String[] args) { / ...

  10. MVC中HTML控件设为只读readonly

    http://www.th7.cn/web/html-css/201501/78934.shtml 1.下拉框设为只读试了试用这个有效: @Html.DropDownListFor(model =&g ...