简介
我们常见的如ls,grep, find等命令,通过–help查看,可以看到它们支持非常多的参数,这说明程序支持的功能非常强大,而且这些参数使得程序弹性更大,也更加灵活。如果我们也想写出这样功能强大的程序,GOption将是一个很好用的功能组件。
GOption提供了对程序参数的解析功能,使用GOption可以很方便地创建支持多参数的应用程序。
数据结构
struct GOptionEntry {
const gchar *long_name; // 长参数名
gchar short_name; // 短参数名
gint flags; // flags标识
GOptionArg arg; // 数据类型
gpointer arg_data; // 参数存储变量
const gchar *description; // 描述
const gchar *arg_description; // 参数描述
};
函数列表
gboolean (*GOptionArgFunc) ()
GOptionContext * g_option_context_new ()
void g_option_context_set_summary ()
const gchar * g_option_context_get_summary ()
void g_option_context_set_description ()
const gchar * g_option_context_get_description ()
const gchar * (*GTranslateFunc) ()
void g_option_context_set_translate_func ()
void g_option_context_set_translation_domain ()
void g_option_context_free ()
gboolean g_option_context_parse ()
gboolean g_option_context_parse_strv ()
void g_option_context_set_help_enabled ()
gboolean g_option_context_get_help_enabled ()
void g_option_context_set_ignore_unknown_options ()
gboolean g_option_context_get_ignore_unknown_options ()
gchar * g_option_context_get_help ()
gboolean g_option_context_get_strict_posix ()
void g_option_context_set_strict_posix ()
void g_option_context_add_main_entries ()
void g_option_context_add_group ()
void g_option_context_set_main_group ()
GOptionGroup * g_option_context_get_main_group ()
GOptionGroup * g_option_group_new ()
GOptionGroup * g_option_group_ref ()
void g_option_group_unref ()
void g_option_group_free ()
void g_option_group_add_entries ()
gboolean (*GOptionParseFunc) ()
void g_option_group_set_parse_hooks ()
void (*GOptionErrorFunc) ()
void g_option_group_set_error_hook ()
void g_option_group_set_translate_func ()
void g_option_group_set_translation_domain ()
函数功能分类
命令行参数解析函数大部分是对GOptionContext对象的操作,少部分是对GOptionGroup对象的操作。
// 创建上下文
GOptionContext * g_option_context_new ()
释放上下文
void g_option_context_free ()
帮助菜单内的摘要
void g_option_context_set_summary ()
const gchar * g_option_context_get_summary ()
帮助菜单内的描述,往往在帮助菜单最后
void g_option_context_set_description ()
const gchar * g_option_context_get_description ()
帮助菜单是否生效
void g_option_context_set_help_enabled ()
gboolean g_option_context_get_help_enabled ()
获取帮助信息
gchar * g_option_context_get_help ()
用户可视化字符串
void g_option_context_set_translate_func ()
void g_option_context_set_translation_domain ()
参数解析
gboolean g_option_context_parse ()
gboolean g_option_context_parse_strv ()
参数解析-忽略错误选项
void g_option_context_set_ignore_unknown_options ()
gboolean g_option_context_get_ignore_unknown_options ()
如设置为TRUE,则会忽略无法识别的选项,如果设置了G_OPTION_REMAINING参数,则无法识别的参数值会保存到G_OPTION_REMAINING。
如果某一选项为隐藏选项,则也会被保存到G_OPTION_REMAINING中。
注:参数可以被隐藏,但仍然会生效
{ "hide", 'e', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &my_hide, "hide me", NULL },
无法解析的参数
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_rest, "Rest goes here", "REST" },
./option-context 1adf 2dafdsaf -a bb -x 3112 -d 12.22 -p 4222 5fads8das90f8da 6dsfsda0f
则无法识别的参数均被存入opt_rest字符串数组中
向上下文添加主条目
void g_option_context_add_main_entries ()
创建组
GOptionGroup * g_option_group_new ()
释放组
void g_option_group_free ()
将组添加到上下文
void g_option_context_add_group ()
上下文的主组
void g_option_context_set_main_group ()
GOptionGroup * g_option_context_get_main_group ()
将一个组设置为主要组,主要组在–help时会默认显示。
当g_option_context_add_main_entries被调用时,如果没有一个main group,则会立即创建一个。
向组添加条目
void g_option_group_add_entries ()
组的引用和解引用
GOptionGroup * g_option_group_ref ()
void g_option_group_unref ()
其他
gboolean g_option_context_get_strict_posix ()
void g_option_context_set_strict_posix ()
gboolean (*GOptionParseFunc) ()
void g_option_group_set_parse_hooks ()
void (*GOptionErrorFunc) ()
void g_option_group_set_error_hook ()
void g_option_group_set_translate_func ()
void g_option_group_set_translation_domain ()
函数功能说明及综合演示
GOption命令行解析总体说明
在GOption体系中,命令行参数解析共有三个元素。
- 条目(GOptionEntry)
- 上下文(GOptionContext)
- 组(GOptionGroup)
一个程序只能有一个上下文,多个条目组成条目数组,条目数组被添加到组中,组被添加到上下文中。每一个命令行参数都由一个GOptionEntry结构进行描述,GOptionEntry结构体的各参数见数据结构部分。下面是对结构体的一个赋值举例。
其含义依次为:长参数、短参数、flags、数据类型、参数存储变量、描述、参数描述
{ “string”, ‘s’, 0, G_OPTION_ARG_STRING, &main_str, “string type”, “str” }
多个GOptionEntry组成一个数组,可以被附加到MainGroup或者其他的Group中。
一个程序只能有一个MainGroup,如果在添加GOptionEntry数组时还没有MainGroup,则会自动创建一个MainGroup。非MainGroup可以创建多个,用来对参数进行分组。MainGroup和非MainGroup可以通过–help看到其差异,如果有非MainGroup,则还可以通过–help-GroupName查看该组的帮助详情。
如果长参数有冲突,则MainGroup的参数不会变化,其他Group的参数会前面加上对应的GroupName-,短参数则会直接被忽略。因此在编码阶段就要尽量避免重复的长参数或短参数。举例来说:
static GOptionEntry entries[] = {
{ "string", 's', 0, G_OPTION_ARG_STRING, &my_str, "Average over N repetitions", "N" },
{ NULL }
};
GOptionEntry group_entries[] = {
{ "string", 's', 0, G_OPTION_ARG_STRING, &my_grp1_string, "Group1 string", "G" },
{ NULL }
};
执行结果如下:
Group1-description
--group1-string=G Group1 string
Application Options:
-s, --string=N Average over N repetitions
命令行参数支持自定义解析函数,此时参数值是可选的,可以有参数值,也可以没有参数值。
GOptionEntry xxx_entries[] = {
{ "cbk", 'C', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, my_callback_parse_optional, NULL, NULL },
{ NULL }
};
GLib提供的参数解析支持参数合并,举个类似的例子,如ls命令,我们可以执行 ls -a -l,也可以执行ls -al。
GOption命令行解析基本演示
源码见glib_examples\glib_regex\glib_regex_basic
#include <glib.h>
static int g_option_test(gint argc, gchar **argv)
{
gboolean ret = -1;
GError *error = NULL;
GOptionContext *context = NULL;
if(argc < 2) {
g_print("Help: %s -h | -? | --help | --help-all \n", argv[0]);
return -1;
}
context = g_option_context_new("< g_option_context_new argument parameter string >");
g_option_context_set_summary (context, "context summary");
g_option_context_set_description(context, "context description");
ret = g_option_context_parse(context, &argc, &argv, &error);
if(TRUE != ret) {
g_print("option parse failed: %s \n", error->message);
return -1;
}
g_option_context_free (context);
return 0;
}
gint main(gint argc, gchar **argv)
{
g_option_test(argc, argv);
return 0;
}
运行结果:
[root@centos7_6 build]# ./glib_option_basic
Help: ./glib_option_basic -h | -? | --help | --help-all
[root@centos7_6 build]# ./glib_option_basic -h
Usage:
glib_option_basic [OPTION?] < g_option_context_new argument parameter string >
context summary
Help Options:
-h, --help Show help options
context description
[root@centos7_6 build]# ./glib_option_basic -?
Usage:
glib_option_basic [OPTION?] < g_option_context_new argument parameter string >
context summary
Help Options:
-h, --help Show help options
context description
[root@centos7_6 build]# ./glib_option_basic -help
Usage:
glib_option_basic [OPTION?] < g_option_context_new argument parameter string >
context summary
Help Options:
-h, --help Show help options
context description
[root@centos7_6 build]# ./glib_option_basic --help-all
Usage:
glib_option_basic [OPTION?] < g_option_context_new argument parameter string >
context summary
Help Options:
-h, --help Show help options
context description
可以看到,本程序默认支持 -h -? --help参数,但对于–help-all参数,目前暂时还没有任何效果。
添加主条目
下面程序演示添加一个主条目的情形。
源码见glib_examples\glib_regex\glib_option_main_entry
#include <glib.h>
static int g_option_test(gint argc, gchar **argv)
{
gboolean ret = -1;
guint index = 0;
GError *error = NULL;
GOptionContext *context = NULL;
gchar *main_str = NULL;
gint main_int = 0;
gchar *main_file = NULL;
gdouble main_double = 0.0;
gint64 main_int64 = 0;
gboolean main_bool = FALSE;
gchar **main_array = NULL;
gchar **main_remain = NULL;
GOptionEntry main_entries[] = {
{ "string", 's', 0, G_OPTION_ARG_STRING, &main_str, "string type", "S" },
{ "int", 'i', 0, G_OPTION_ARG_INT, &main_int, "int type", "I" },
{ "file", 'f', 0, G_OPTION_ARG_FILENAME, &main_file, NULL, NULL },
{ "double", 'd', 0, G_OPTION_ARG_DOUBLE, &main_double, NULL, NULL },
{ "int64", 'l', 0, G_OPTION_ARG_INT64, &main_int64, NULL, NULL },
{ "bool", 'b', 0, G_OPTION_ARG_NONE, &main_bool, "bool type, -b with no value, no arg", NULL },
{ "array", 'a', 0, G_OPTION_ARG_STRING_ARRAY, &main_array, "array type -a 1, -a 2", NULL },
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &main_remain, "Rest goes here", "REST" },
{ NULL }
};
if(argc < 2) {
g_print("Help: %s -h | -? | --help | --help-all \n", argv[0]);
return -1;
}
context = g_option_context_new("< g_option_context_new argument parameter string >");
g_option_context_set_summary (context, "context summary");
g_option_context_set_description(context, "context description");
g_option_context_add_main_entries(context, main_entries, NULL);
ret = g_option_context_parse(context, &argc, &argv, &error);
if(TRUE != ret) {
g_print("option parse failed: %s \n", error->message);
return -1;
}
g_print("main_str: %s \n", main_str);
g_print("main_int: %d \n", main_int);
g_print("main_file: %s \n", main_file);
g_print("main_double: %f \n", main_double);
g_print("main_int64: %4lld \n", main_int64);
g_print("main_bool: %s \n", main_bool?"TRUE":"FALSE");
index = 0;
while((NULL != main_array) && (NULL != main_array[index]) ) {
g_print("main_array[%d]: %s \n", index, main_array[index]);
index ++;
}
index = 0;
while((NULL != main_remain) && (NULL != main_remain[index]) ) {
g_print("main_remain[%d]: %s \n", index, main_remain[index]);
index ++;
}
g_free(main_str);
g_free(main_file);
g_strfreev(main_array);
g_strfreev(main_remain);
g_option_context_free (context);
return 0;
}
gint main(gint argc, gchar **argv)
{
g_option_test(argc, argv);
return 0;
}
运行结果:
[root@centos7_6 build]# ./glib_option_main_entry -s "ab cd" -i 101 -f /home/test.txt -d 100.25 -l 1234567890123456789 -b -a 3 -a 4 dummy-arg
main_str: ab cd
main_int: 101
main_file: /home/test.txt
main_double: 100.250000
main_int64: 1234567890123456789
main_bool: TRUE
main_array[0]: 3
main_array[1]: 4
main_remain[0]: dummy-arg
bool类型变量比较特别,该命令行参数不带数值,只要加上-b,则bool的值为TRUE,否则为FALSE。array类型变量,需要在命令行分别传入,如:-a 3 -a 4。如果有未被识别的参数,则会被存到main_remain数组变量中。另外,解析出str file array类型的变量后一定要记得释放内存。
添加多个主条目
源码见glib_examples\glib_regex\glib_option_multi_main_entries
#include <glib.h>
static gint g_option_test(gint argc, gchar **argv)
{
gboolean ret = -1;
guint index = 0;
GError *error = NULL;
GOptionContext *context = NULL;
gchar *main_str = NULL;
gint main_int = 0;
gchar *main_file = NULL;
gdouble main_double = 0.0;
gint64 main_int64 = 0;
gboolean main_bool = FALSE;
gchar **main_array = NULL;
gchar **main_remain = NULL;
GOptionEntry main_entries[] = {
{ "string", 's', 0, G_OPTION_ARG_STRING, &main_str, "string type", "str" },
{ "int", 'i', 0, G_OPTION_ARG_INT, &main_int, "int type", "int_value" },
{ "file", 'f', 0, G_OPTION_ARG_FILENAME, &main_file, NULL, NULL },
{ "double", 'd', 0, G_OPTION_ARG_DOUBLE, &main_double, NULL, NULL },
{ "int64", 'l', 0, G_OPTION_ARG_INT64, &main_int64, NULL, NULL },
{ "bool", 'b', 0, G_OPTION_ARG_NONE, &main_bool, "bool type, -b with no value, no arg", NULL },
{ "array", 'a', 0, G_OPTION_ARG_STRING_ARRAY, &main_array, "array type -a 1, -a 2", NULL },
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &main_remain, "Rest goes here", "REST" },
{ NULL }
};
guint main2_uint = 0;
gint main2_hide_int = 0;
gchar *main2_hide_str = NULL;
GOptionEntry main_entries2[] = {
{ "uint", 'U', 0, G_OPTION_ARG_INT, &main2_uint, "unsigned int type", "U" },
{ "hide-int", 'I', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_INT, &main2_hide_int, "option will be hidden, but it still works", NULL },
{ "hide-str", 'S', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &main2_hide_str, "option will be hidden, but it still works", NULL },
{ NULL }
};
if(argc < 2) {
g_print("Help: %s -h | -? | --help | --help-all \n", argv[0]);
return -1;
}
context = g_option_context_new("< g_option_context_new argument parameter string >");
g_option_context_set_summary (context, "context summary");
g_option_context_set_description(context, "context description");
//g_option_context_set_ignore_unknown_options(context, TRUE);
g_option_context_add_main_entries(context, main_entries, NULL);
g_option_context_add_main_entries(context, main_entries2, NULL);
ret = g_option_context_parse(context, &argc, &argv, &error);
if(TRUE != ret) {
g_print("option parse failed: %s \n", error->message);
return -1;
}
#if 1 // main_entries
g_print("main_str: %s \n", main_str);
g_print("main_int: %d \n", main_int);
g_print("main_file: %s \n", main_file);
g_print("main_double: %f \n", main_double);
g_print("main_int64: %4lld \n", main_int64);
g_print("main_bool: %s \n", main_bool?"TRUE":"FALSE");
index = 0;
while((NULL != main_array) && (NULL != main_array[index]) ) {
g_print("main_array[%d]: %s \n", index, main_array[index]);
index ++;
}
index = 0;
while((NULL != main_remain) && (NULL != main_remain[index]) ) {
g_print("main_remain[%d]: %s \n", index, main_remain[index]);
index ++;
}
g_free(main_str);
g_free(main_file);
g_strfreev(main_array);
g_strfreev(main_remain);
#endif
#if 1 // main_entries2
g_print("main2_uint: %d \n", main2_uint);
g_print("main2_hide_int: %d \n", main2_hide_int);
g_print("main2_hide_str: %s \n", main2_hide_str);
g_free(main2_hide_str);
#endif
g_option_context_free (context);
return 0;
}
gint main(gint argc, gchar **argv)
{
g_option_test(argc, argv);
return 0;
}
运行结果:
[root@centos7_6 build]# ./glib_option_multi_main_entries --help
Usage:
glib_option_multi_main_entries [OPTION?] REST < g_option_context_new argument parameter string >
context summary
Help Options:
-h, --help Show help options
Application Options:
-s, --string=str string type
-i, --int=int_value int type
-f, --file
-d, --double
-l, --int64
-b, --bool bool type, -b with no value, no arg
-a, --array array type -a 1, -a 2
-U, --uint=U unsigned int type
context description
[root@centos7_6 build]# ./glib_option_multi_main_entries -s "ab cd" -i 101 -f /home/test.txt -d 100.25 -l 1234567890123456789 -b -a 3 -a 4 dummy-arg -I 700 -S str2
main_str: ab cd
main_int: 101
main_file: /home/test.txt
main_double: 100.250000
main_int64: 1234567890123456789
main_bool: TRUE
main_array[0]: 3
main_array[1]: 4
main_remain[0]: dummy-arg
main2_uint: 0
main2_hide_int: 700
main2_hide_str: str2
如果有多个主条目,则所有主条目会被合并,都显示在Application Options组。一种用法是将一组主条目全部设置为隐藏参数,这样在–help时无法看到,但仍可以使用它。参数可以被隐藏,但仍然会生效。添加一个隐藏参数的示例代码片段如下:
{ "hide", 'e', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &my_hide, "hide me", NULL },
可选参数效果
本程序演示使用g_option_context_add_main_entries
函数再添加一个MainGroup组,这个组的参数是一个回调函数类型,且参数值是可选的。
源码见glib_examples\glib_regex\glib_option_callback
#include <glib.h>
static gboolean cbk_opt_flag = FALSE;
static gint cbk_opt_int = 0;
static gboolean callback_parse_optional (const gchar *option_name, const gchar *value,
gpointer data, GError **error)
{
cbk_opt_flag = TRUE;
if (value)
cbk_opt_int = atoi (value);
else
cbk_opt_int = 0;
return TRUE;
}
static int g_option_test(gint argc, gchar **argv)
{
gboolean ret = -1;
guint index = 0;
GError *error = NULL;
GOptionContext *context = NULL;
gchar *main_str = NULL;
gint main_int = 0;
gchar *main_file = NULL;
gdouble main_double = 0.0;
gint64 main_int64 = 0;
gboolean main_bool = FALSE;
gchar **main_array = NULL;
gchar **main_remain = NULL;
GOptionEntry main_entries[] = {
{ "string", 's', 0, G_OPTION_ARG_STRING, &main_str, "string type", "str" },
{ "int", 'i', 0, G_OPTION_ARG_INT, &main_int, "int type", "int_value" },
{ "file", 'f', 0, G_OPTION_ARG_FILENAME, &main_file, NULL, NULL },
{ "double", 'd', 0, G_OPTION_ARG_DOUBLE, &main_double, NULL, NULL },
{ "int64", 'l', 0, G_OPTION_ARG_INT64, &main_int64, NULL, NULL },
{ "bool", 'b', 0, G_OPTION_ARG_NONE, &main_bool, "bool type, -b with no value, no arg", NULL },
{ "array", 'a', 0, G_OPTION_ARG_STRING_ARRAY, &main_array, "array type -a 1, -a 2", NULL },
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &main_remain, "Rest goes here", "REST" },
{ NULL }
};
guint main2_uint = 0;
gint main2_hide_int = 0;
gchar *main2_hide_str = NULL;
GOptionEntry main_entries2[] = {
{ "uint", 'U', 0, G_OPTION_ARG_INT, &main2_uint, "unsigned int type", "U" },
{ "hide-int", 'I', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_INT, &main2_hide_int, "option will be hidden, but it still works", NULL },
{ "hide-str", 'S', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &main2_hide_str, "option will be hidden, but it still works", NULL },
{ NULL }
};
GOptionEntry main_entries3[] = {
{ "optional", 'O', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, callback_parse_optional, "optional", "int value" },
{ NULL }
};
if(argc < 2) {
g_print("Help: %s -h | -? | --help | --help-all \n", argv[0]);
return -1;
}
context = g_option_context_new("< g_option_context_new argument parameter string >");
g_option_context_set_summary (context, "context summary");
g_option_context_set_description(context, "context description");
//g_option_context_set_ignore_unknown_options(context, TRUE);
g_option_context_add_main_entries(context, main_entries, NULL);
g_option_context_add_main_entries(context, main_entries2, NULL);
g_option_context_add_main_entries(context, main_entries3, NULL);
ret = g_option_context_parse(context, &argc, &argv, &error);
if(TRUE != ret) {
g_print("option parse failed: %s \n", error->message);
return -1;
}
#if 1 // main_entries
g_print("main_str: %s \n", main_str);
g_print("main_int: %d \n", main_int);
g_print("main_file: %s \n", main_file);
g_print("main_double: %f \n", main_double);
g_print("main_int64: %4lld \n", main_int64);
g_print("main_bool: %s \n", main_bool?"TRUE":"FALSE");
index = 0;
while((NULL != main_array) && (NULL != main_array[index]) ) {
g_print("main_array[%d]: %s \n", index, main_array[index]);
index ++;
}
index = 0;
while((NULL != main_remain) && (NULL != main_remain[index]) ) {
g_print("main_remain[%d]: %s \n", index, main_remain[index]);
index ++;
}
g_free(main_str);
g_free(main_file);
g_strfreev(main_array);
g_strfreev(main_remain);
#endif
#if 1 // main_entries2
g_print("main2_uint: %d \n", main2_uint);
g_print("main2_hide_int: %d \n", main2_hide_int);
g_print("main2_hide_str: %s \n", main2_hide_str);
g_free(main2_hide_str);
#endif
#if 1 // main_entries3
g_print("cbk_opt_flag:%s \n", cbk_opt_flag?"TRUE":"FALSE");
g_print("cbk_opt_int:%d \n", cbk_opt_int);
#endif
g_option_context_free (context);
return 0;
}
gint main(gint argc, gchar **argv)
{
g_option_test(argc, argv);
return 0;
}
运行结果:
[root@centos7_6 build]# ./glib_option_callback -s "ab cd" -i 101 -f /home/test.txt -d 100.25 -l 1234567890123456789 -b -a 3 -a 4 dummy-arg -I 700 -S str2 -O 999
main_str: ab cd
main_int: 101
main_file: /home/test.txt
main_double: 100.250000
main_int64: 1234567890123456789
main_bool: TRUE
main_array[0]: 3
main_array[1]: 4
main_remain[0]: dummy-arg
main2_uint: 0
main2_hide_int: 700
main2_hide_str: str2
cbk_opt_flag:TRUE
cbk_opt_int:999
[root@centos7_6 build]# ./glib_option_callback -s "ab cd" -i 101 -f /home/test.txt -d 100.25 -l 1234567890123456789 -b -a 3 -a 4 dummy-arg -I 700 -S str2 -O
main_str: ab cd
main_int: 101
main_file: /home/test.txt
main_double: 100.250000
main_int64: 1234567890123456789
main_bool: TRUE
main_array[0]: 3
main_array[1]: 4
main_remain[0]: dummy-arg
main2_uint: 0
main2_hide_int: 700
main2_hide_str: str2
cbk_opt_flag:TRUE
cbk_opt_int:0
[root@centos7_6 build]# ./glib_option_callback -s "ab cd" -i 101 -f /home/test.txt -d 100.25 -l 1234567890123456789 -b -a 3 -a 4 dummy-arg -I 700 -S str2
main_str: ab cd
main_int: 101
main_file: /home/test.txt
main_double: 100.250000
main_int64: 1234567890123456789
main_bool: TRUE
main_array[0]: 3
main_array[1]: 4
main_remain[0]: dummy-arg
main2_uint: 0
main2_hide_int: 700
main2_hide_str: str2
cbk_opt_flag:FALSE
cbk_opt_int:0
上述演示示例中,-O选项的参数可选,其设置方法如下:
{ "optional", 'O', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, callback_parse_optional, "optional", "int value" },
该选项在使用时有以下几种情形:
- 如果执行时不带-O选项,则cbk_opt_flag的值为FALSE
- 如果执行时带了-O选项,但后面不跟任何参数,则cbk_opt_flag的值为TRUE,其值为0
- 如果执行时带了-O选项,后面也跟了参数,则cbk_opt_flag的值为TRUE,其值为所跟参数
添加多个主条目和非主条目
GOption支持添加多个主条目,也支持添加多个非主条目,下面是演示程序。
源码见glib_examples\glib_regex\glib_option_multi_entries
#include <glib.h>
static gboolean cbk_opt_flag = FALSE;
static gint cbk_opt_int = 0;
static gboolean callback_parse_optional (const gchar *option_name, const gchar *value,
gpointer data, GError **error)
{
cbk_opt_flag = TRUE;
if (value)
cbk_opt_int = atoi (value);
else
cbk_opt_int = 0;
return TRUE;
}
static int g_option_test(gint argc, gchar **argv)
{
gboolean ret = -1;
guint index = 0;
GError *error = NULL;
GOptionContext *context = NULL;
gchar *main_str = NULL;
gint main_int = 0;
gchar *main_file = NULL;
gdouble main_double = 0.0;
gint64 main_int64 = 0;
gboolean main_bool = FALSE;
gchar **main_array = NULL;
gchar **main_remain = NULL;
GOptionEntry main_entries[] = {
{ "string", 's', 0, G_OPTION_ARG_STRING, &main_str, "string type", "str" },
{ "int", 'i', 0, G_OPTION_ARG_INT, &main_int, "int type", "int_value" },
{ "file", 'f', 0, G_OPTION_ARG_FILENAME, &main_file, NULL, NULL },
{ "double", 'd', 0, G_OPTION_ARG_DOUBLE, &main_double, NULL, NULL },
{ "int64", 'l', 0, G_OPTION_ARG_INT64, &main_int64, NULL, NULL },
{ "bool", 'b', 0, G_OPTION_ARG_NONE, &main_bool, "bool type, -b with no value, no arg", NULL },
{ "array", 'a', 0, G_OPTION_ARG_STRING_ARRAY, &main_array, "array type -a 1, -a 2", NULL },
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &main_remain, "Rest goes here", "REST" },
{ NULL }
};
guint main2_uint = 0;
gint main2_hide_int = 0;
gchar *main2_hide_str = NULL;
GOptionEntry main_entries2[] = {
{ "uint", 'U', 0, G_OPTION_ARG_INT, &main2_uint, "unsigned int type", "U" },
{ "hide-int", 'I', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_INT, &main2_hide_int, "option will be hidden, but it still works", NULL },
{ "hide-str", 'S', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &main2_hide_str, "option will be hidden, but it still works", NULL },
{ NULL }
};
GOptionEntry main_entries3[] = {
{ "optional", 'O', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, callback_parse_optional, "optional", "int value" },
{ NULL }
};
GOptionGroup *group1;
GOptionGroup *group2;
gint group1_int = 0;
gchar *group1_str = NULL;
GOptionEntry group1_entries[] = {
{ "grp1-int", 'X', 0, G_OPTION_ARG_INT, &group1_int, "group1 int", "X" },
{ "grp1-str", 0, 0, G_OPTION_ARG_STRING, &group1_str, "string type", "str" },
{ NULL }
};
gint group2_int = 0;
gchar *group2_str = NULL;
GOptionEntry group2_entries[] = {
{ "grp2-int", 'Y', 0, G_OPTION_ARG_INT, &group2_int, "group2 int", "Y" },
{ "grp2-str", 0, 0, G_OPTION_ARG_STRING, &group2_str, "string type", "str" },
{ NULL }
};
if(argc < 2) {
g_print("Help: %s -h | -? | --help | --help-all \n", argv[0]);
return -1;
}
context = g_option_context_new("< g_option_context_new argument parameter string >");
g_option_context_set_summary (context, "context summary");
g_option_context_set_description(context, "context description");
//g_option_context_set_ignore_unknown_options(context, TRUE);
g_option_context_add_main_entries(context, main_entries, NULL);
g_option_context_add_main_entries(context, main_entries2, NULL);
g_option_context_add_main_entries(context, main_entries3, NULL);
group1 = g_option_group_new ("group1", "Group1-Description", "Group1-Help", NULL, NULL);
g_option_group_add_entries (group1, group1_entries);
g_option_context_add_group (context, group1);
group2 = g_option_group_new ("group2", "Group2-Description", "Group2-Help", NULL, NULL);
g_option_group_add_entries (group2, group2_entries);
g_option_context_add_group (context, group2);
ret = g_option_context_parse(context, &argc, &argv, &error);
if(TRUE != ret) {
g_print("option parse failed: %s \n", error->message);
return -1;
}
#if 1 // main_entries
g_print("main_str: %s \n", main_str);
g_print("main_int: %d \n", main_int);
g_print("main_file: %s \n", main_file);
g_print("main_double: %f \n", main_double);
g_print("main_int64: %4lld \n", main_int64);
g_print("main_bool: %s \n", main_bool?"TRUE":"FALSE");
index = 0;
while((NULL != main_array) && (NULL != main_array[index]) ) {
g_print("main_array[%d]: %s \n", index, main_array[index]);
index ++;
}
index = 0;
while((NULL != main_remain) && (NULL != main_remain[index]) ) {
g_print("main_remain[%d]: %s \n", index, main_remain[index]);
index ++;
}
g_free(main_str);
g_free(main_file);
g_strfreev(main_array);
g_strfreev(main_remain);
#endif
#if 1 // main_entries2
g_print("main2_uint: %d \n", main2_uint);
g_print("main2_hide_int: %d \n", main2_hide_int);
g_print("main2_hide_str: %s \n", main2_hide_str);
g_free(main2_hide_str);
#endif
#if 1 // main_entries3
g_print("cbk_opt_flag:%s \n", cbk_opt_flag?"TRUE":"FALSE");
g_print("cbk_opt_int:%d \n", cbk_opt_int);
#endif
#if 1 //group entries
g_print("group1_int: %d \n", group1_int);
g_print("group1_str: %s \n", group1_str);
g_free(group1_str);
g_print("group2_int: %d \n", group2_int);
g_print("group2_str: %s \n", group2_str);
g_free(group2_str);
#endif
g_option_context_free (context);
return 0;
}
gint main(gint argc, gchar **argv)
{
g_option_test(argc, argv);
return 0;
}
运行结果:
[root@centos7_6 build]# ./glib_option_multi_entries --help
Usage:
glib_option_multi_entries [OPTION?] REST < g_option_context_new argument parameter string >
context summary
Help Options:
-h, --help Show help options
--help-all Show all help options
--help-group1 Group1-Help
--help-group2 Group2-Help
Application Options:
-s, --string=str string type
-i, --int=int_value int type
-f, --file
-d, --double
-l, --int64
-b, --bool bool type, -b with no value, no arg
-a, --array array type -a 1, -a 2
-U, --uint=U unsigned int type
-O, --optional=int value optional
context description
[root@centos7_6 build]# ./glib_option_multi_entries --help-all
Usage:
glib_option_multi_entries [OPTION?] REST < g_option_context_new argument parameter string >
context summary
Help Options:
-h, --help Show help options
--help-all Show all help options
--help-group1 Group1-Help
--help-group2 Group2-Help
Group1-Description
-X, --grp1-int=X group1 int
--grp1-str=str string type
Group2-Description
-Y, --grp2-int=Y group2 int
--grp2-str=str string type
Application Options:
-s, --string=str string type
-i, --int=int_value int type
-f, --file
-d, --double
-l, --int64
-b, --bool bool type, -b with no value, no arg
-a, --array array type -a 1, -a 2
-U, --uint=U unsigned int type
-O, --optional=int value optional
context description
[root@centos7_6 build]# ./glib_option_multi_entries -s "ab cd" -i 101 -f /home/test.txt -d 100.25 -l 1234567890123456789 -b -a 3 -a 4 dummy-arg -I 700 -S str2 -O 999 -X 666 -Y 777 --grp1-str group1-strings --grp2-str group2-strings
main_str: ab cd
main_int: 101
main_file: /home/test.txt
main_double: 100.250000
main_int64: 1234567890123456789
main_bool: TRUE
main_array[0]: 3
main_array[1]: 4
main_remain[0]: dummy-arg
main2_uint: 0
main2_hide_int: 700
main2_hide_str: str2
cbk_opt_flag:TRUE
cbk_opt_int:999
group1_int: 666
group1_str: group1-strings
group2_int: 777
group2_str: group2-strings
当执行程序时,带参数-h或–help可查看用法,在Help Options下面会多出--help-group1
及--help-group2
两个提示项,此时如果执行--help-group1
或者--help-all
,就会出现该组的详细帮助信息。