目錄
一.gflags 介紹
二.gflags安裝
三.gflags使用
1.包含頭文件
2.定義參數
3.訪問參數
4.不同文件訪問參數
5.初始化所有參數
6.運行參數設置
7.配置文件的使用
8.特殊參數標識
四.總結
一.gflags 介紹
????????gflags 是 Google 開發的一個開源庫,用于 C++ 應用程序中命令行參數的聲明、定義和解析。gflags 庫提供了一種簡單的方式來添加、解析和文檔化命令行標志(flags),使得程序可以根據不同的運行時配置進行調整。
它具有如下幾個特點:
- 易于使用:gflags 提供了一套簡單直觀的 API 來定義和解析命令行標志,使得開發者可以輕松地為應用程序添加新的參數;
- 自動幫助和文檔:gflags 可以自動生成每個標志的幫助信息和文檔,這有助于用戶理解如何使用程序及其參數;
- 類型安全:gflags 支持多種數據類型的標志,包括布爾值、整數、字符串等,并且提供了類型檢查和轉換;
- 多平臺支持:gflags 可以在多種操作系統上使用,包括 Windows、Linux 和 macOS;
- 可擴展性:gflags 允許開發者自定義標志的注冊和解析邏輯,提供了強大的擴展性。
官方文檔:https://gflags.github.io/gflags/
代碼倉庫:https://github.com/gflags/gflags.git
二.gflags安裝
直接命令安裝:
sudo apt-get install libgflags-dev
源碼安裝:
# 下載源碼
git clone https://github.com/gflags/gflags.git
# 切換目錄
cd gflags/
mkdir build
cd build/
# 生成 Makefile
cmake ..
# 編譯代碼
make
# 安裝
make install
????????未報錯則安裝完畢。
三.gflags使用
1.包含頭文件
????????使用 gflags 庫來定義/解析命令行參數必須包含如下頭文件。
#include <gflags/gflags.h>
2.定義參數
????????利用 gflag 提供的宏定義來定義參數。該宏的 3 個參數分別為命令行參數名,參數默認值,參數的幫助信息。
DEFINE_bool(reuse_addr, true, "是否開始網絡地址重用選項");
DEFINE_int32(log_level, 1, "日志等級:1-DEBUG, 2-WARN, 3-ERROR");
DEFINE_string(log_file, "stdout", "日志輸出位置設置,默認為標準輸出");
gflags 支持定義多種類型的宏函數:
DEFINE_bool
DEFINE_int32
DEFINE_int64
DEFINE_uint64
DEFINE_double
DEFINE_string
3.訪問參數
????????我們可以在程序中通過 FLAGS_name 像正常變量一樣訪問標志參數。比如在上面的例子中,我們可以通過 FLAGS_big_menu 和 FLAGS_languages 變量來訪問命令行參數。
4.不同文件訪問參數
????????如果想再另外一個文件訪問當前文件的參數,以參數 FLAGS_big_menu 為例,我們可以使用用宏 DECLARE_bool(big_menu)來聲明引入這個參數。
????????其實這個宏就相當于做了 extern FLAGS_big_menu, 定義外部鏈接屬性。
5.初始化所有參數
????????當我們定義好參數后,需要告訴可執行程序去處理解析命令行傳入的參數,使得FLAGS_*變量能得到正確賦值。我們需要在 main 函數中,調用下面的函數來解決命令行傳入的所有參數。
google::ParseCommandLineFlags(&argc, &argv, true);
- argc 和 argv 就是 main 的入口參數;
- 第三個參數被稱為 remove_flags。如果它為 true, 表示ParseCommandLineFlags 會從 argv 中移除標識和它們的參數,相應減少 argc 的值;如果它為 false,ParseCommandLineFlags 會保留 argc 不變,但將會重新調整它們的順序,使得標識再前面。這里的說明比較晦澀,下面我在Linux上寫代碼進行輸出來演示。
????????首先是第三個參數設置為false,我在命令行對命令行參數進行設置,而不使用默認值,因為如果使用默認值的話,argc的值在第三個參數設置為true和false的情況下是一樣的,就看不出區別。
代碼如下:
#include <gflags/gflags.h>
#include <iostream>DEFINE_string(ip, "127.0.0.1", "這是服務器監聽ip地址,格式:127.0.0.1");
DEFINE_int32(port, 8080, "這是服務器監聽端口,格式:8080");
DEFINE_bool(enableDebug, true, "是否開啟調試模式,格式:true/false");int main(int argc, char* argv[])
{google::ParseCommandLineFlags(&argc, &argv, false);std::cout << "argc的值是:" << argc << std::endl;std::cout << "FLAGS_作為前綴版本:" << std::endl;std::cout << FLAGS_ip << std::endl;std::cout << FLAGS_port << std::endl;std::cout << FLAGS_enableDebug << std::endl;std::cout << "argv數組進行訪問的版本" << std::endl;for(int i = 0;i < argc;i++){std::cout << argv[i] << std::endl;}return 0;
}
shell命令:
./main --ip="47.235.41.48" --port=9090 --enableDebug=false
輸出:
????????可以看到,argv中包含了完整的命令行參數,包括可執行文件總共四個,下面我們看看第三個參數為true的情況。
代碼只是將第三個參數設置為true,其它不變,輸出如下:
? ? ? ? 這時候argv中就只有可執行文件的命令行內容了,argc也相應的變成了1,。也就是說,設置為true的情況下將gflags自定義的命令行參數給刪除了,argc也相應減少。設置為true是我個人經常使用和推薦的版本,因為訪問gflags命令行參數時,我們直接使用“FLAGS_”作為前綴即可,這樣不用自己進行字符串解析,非常的方便。?
6.運行參數設置
????????gflags 為我們提供了多種命令行設置參數的方式。
string 和 int 設置參數
exec --log_file="./main.log"
exec -log_file="./main.log"
exec --log_file "./main.log"
exec -log_file "./main.log"
????????int版本的設置則是不加雙引號,其它沒有什么不同。
bool 設置參數
exec --reuse_addr
exec --noreuse_addr
exec --reuse_addr=true
exec --reuse_addr=false
? ? ? ? 上面命令行中沒有聲明true或者false的前兩行的意思就是設置為true,簡化了書寫。
????????另外有一點專門的說明,--單獨使用將會終止標識的處理。比如在 exec -f1 1 -- -f2 2 中, f1 被認為是一個標識,但 f2 不會。
7.配置文件的使用
????????配置文件的使用,其實就是為了讓程序的運行參數配置更加標準化,不需要每次運行的時候都手動收入每個參數的數值,而是通過配置文件,一次編寫,永久使用。
????????需要注意的是,配置文件中選項名稱必須與代碼中定義的選項名稱一致。
例子,配置文件main.conf
--ip="222.2.2.2"
--port=7777
--enableDebug=false
命令行
./main --flagfile=./main.conf
????????這里需要用到--flagfile這個選項來指明配置文件的地址。
? ? ? ? 輸出時則輸出配置文件中的內容。
8.特殊參數標識
????????gflags 也默認為我們提供了幾個特殊的標識。
--help # 顯示文件中所有標識的幫助信息
--helpfull # 和-help 一樣, 幫助信息更全面一些
--helpshort # 只顯示當前執行文件里的標志
--helpxml # 以 xml 方式打印,方便處理
--version # 打印版本信息,由 google::SetVersionString()設定
--flagfile -flagfile=f #從文件 f 中讀取命令行參數
四.總結
? ? ? ? 以上就是gflags的使用,非常的簡單,并且允許在程序各個地方進行命令行參數的定義,不止在main函數中,但有一個缺點,也就是在兩個文件中定義了名字相同的命令行參數,并且這兩個文件進行了鏈接,那么程序就會編譯報錯,這就要求我們開發人員要格外小心。