3_13_GLib库入门与实践_命令行解析

简介

我们常见的如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,就会出现该组的详细帮助信息。

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值