• linux 下的帮助接口argp_parse()实战


    linux 下的帮助接口argp_parse()

    选项能够改变程序的运行轨迹,而帮助系统需要让用户知道有哪些选项可以使用。
    gnu 的帮助系统已经为我们写了很多代码,我们只需要调用argp_parse 函数就可以了.
    ----------------------------------------
    argp_parse() 的基本用法
    ----------------------------------------
    argp_parse需要我们定义一个帮助表,看一下它的调用参数: 6个,挺复杂

    int argp_parse (const struct argp * __argp,
                   int __argc, char ** __argv,
                   unsigned __flags, int * __arg_index,
                   void * __input);

    第1项是一个结构指针
    第2项,第3项argc,argv 就是c语言的命令行参数选项.
    第4项, flag.
    第5项,index, 第6项input
    不明白的可以都设置为0,看看是什么情况.

    1. #include
    2. #include
    3. int main (int argc, char **argv)
    4. {
    5. return argp_parse (0, argc, argv, 0, 0, 0);
    6. }

    argc,argv不能填0, 否则会段错误.
    该程序编译运行后,果然能很好的工作,出现了默认的帮助菜单,与标准linux的显示风格一致.
    现在想加入版本信息.只需要加一个全局变量即可.
    const char *argp_program_version = "version 1.0";
    工作的也很好!
    这些都是系统的东西,我们基本上没有做什么.
    注意这里所说的系统就是库,相对于用户来说的,以后都沿用这种说法.


    现在我们想加入一个自己的选项, 先定义一个选项表,里面包含一个选项.
    struct argp_option options[] =
    {
        { "dot", 'd', "NUM", OPTION_ARG_OPTIONAL, "Show some dots on the screen"},
        { 0 },
    };

    选项还是容易理解的,如下定义,其中1,3,5项都是字符串,第1项是长选项名称
      type = struct argp_option {
          const char *name;
          int key;
          const char *arg;
          int flags;
          const char *doc;
          int group;
      }

     第1项是长选项名称
      第3项是参数提示信息,上例"NUM" 字符串会跟在长选项提示信息中.
      第5项是帮助信息.
      第2项是短选项,一个字符,所以用''括住,它是作为key来使用的, 各个选项是靠它来区分的.
      第4项flags, OPTION_ARG_OPTIONAL 表示该参数是可选的(可以跟参数或不跟参数)
      第6项group, 是分组数值,后面使用时就理解了.

    那这个options 表如何使用呢?
    后面,有一个重要的结构要出场了,它就是 struct argp, 有7个成员
    type = struct argp {
      const struct argp_option *options;
      argp_parser_t parser;
      const char *args_doc;
      const char *doc;
      const struct argp_child *children;
      char *(*help_filter)(int, const char *, void *);
      const char *argp_domain;
    }
    这个结构太复杂,要慢慢通过实例来理解. 不过不理解的可以先置空.
    第一项 options 指针显然指向我们定义的argp_option 数组
    第2项 parser 是一个回调函数。 你想,当我们定义了一个选项,通过调用 --help系统把帮助信息给我们显示了出来.
        当我们从命令行输入自定义选项时,怎样解释这个选项,也是需要我们来解释的,所以我们要定义这个解释函数。
    第3项,4项都是字符串,用用就知道了,其它都置0先不管。

    1. #include
    2. #include
    3. #include
    4. const char *argp_program_version = "version 1.0";
    5. struct argp_option options[] =
    6. {
    7. { "dot", 'd', "NUM", OPTION_ARG_OPTIONAL, "Show some dots on the screen"},
    8. { 0 },
    9. };
    10. //key 是命令行中传入的选项的key, 如果该key在options表中定义了参数,arg传递的是命令行中的选项参数.
    11. static int parse_opt (int key, char *arg, struct argp_state *state)
    12. {
    13. switch (key)
    14. {
    15. case 'd':
    16. {
    17. unsigned int i;
    18. unsigned int dots = 1;
    19. if (arg != NULL) dots = atoi (arg);
    20. printf("you input option d number is :%d\n",dots);
    21. for (i = 0; i < dots; i++) printf (".");
    22. printf("\n");
    23. break;
    24. }
    25. }
    26. return 0; //很关键,否则无信息提示了!!
    27. }
    28. struct argp argp = {options, parse_opt, "," }; //参数3是跟在使用提示的字符串
    29. int main (int argc, char **argv)
    30. {
    31. return argp_parse (&argp, argc, argv, 0, 0, 0);
    32. }

    "have a rest!", 目前只定义了一个可选参数OPTION_ARG_OPTIONAL, 类型为"NUM", 工作运行良好, 已经可以应付一般的帮助要求了.
    解释一下吧,为什么设置了argp_program_version 就能显示出版本号? argp_parse 是怎样得知信息的?
    解释清这个问题,需要刨老底了.
    我查看了它的库代码,原来如此. (库代码请参考链接下载)
    ./gnu/argp-pv.c|25| const char *argp_program_version
    ./gnu/argp.h|448| extern const char *argp_program_version;

    使用时:
          if (argp_program_version)
          {
              ....
          }
    就是说,库里边定义了argp_program_version变量,但它的值是NULL,如果用户也定义了argp_program_version,并且不为0,
    那应用就会链接你定义的变量, 由于其不为0, 所以就可以添加版本显示选项了.

    ----------------------------------------
    argp 的高级用法
    ----------------------------------------
    1. 介绍2个key参数: ARGP_KEY_ARG,ARGP_KEY_END, 用来处理参数
        我们知道,命令行除了可以带选项,还可以带参数,每当系统分析到参数时,就会回调parse_opt, 并传递key参数为ARGP_KEY_ARG,
        当所有参数处理完时,传递ARGP_KEY_END key 参数
         在parse_opt 函数中,会有如下分支
        case ARGP_KEY_ARG
        case ARGP_KEY_END
    2. 添加分组信息,使输出帮助信息更加明了
    参考下面程序:

    1. #include
    2. #include
    3. #include
    4. const char *argp_program_version = "version 1.0";
    5. struct argp_option options[] =
    6. {
    7. { 0, 0, 0, 0, "Program Options:", 7}, //自定义信息这里定义为7
    8. { "dot", 'd', "NUM", OPTION_ARG_OPTIONAL, "Show some dots on the screen"},
    9. { 0, 0, 0, 0, "Informational Options:", -1}, //系统help 信息属于-1分组
    10. { 0 },
    11. };
    12. static int parse_opt (int key, char *arg, struct argp_state *state)
    13. {
    14. int *arg_count = state->input;
    15. switch (key)
    16. {
    17. case 'd':
    18. {
    19. unsigned int i;
    20. unsigned int dots = 1;
    21. if (arg != NULL) dots = atoi (arg);
    22. for (i = 0; i < dots; i++) printf (".");
    23. printf("\n");
    24. break;
    25. }
    26. case ARGP_KEY_ARG:
    27. (*arg_count)--;
    28. if (*arg_count >= 0) printf (" %s", arg);
    29. break;
    30. case ARGP_KEY_END:
    31. printf ("\n");
    32. if (*arg_count >= 4) argp_failure (state, 1, 0, "too few arguments");
    33. else if (*arg_count < 0) argp_failure (state, 1, 0, "too many arguments");
    34. break;
    35. }
    36. return 0; //很关键,否则无信息提示了!!
    37. }
    38. struct argp argp = {options, parse_opt, "[param1 [param2 [param3 [param4]]]]" };
    39. int main (int argc, char **argv)
    40. {
    41. int arg_count = 4;
    42. return argp_parse (&argp, argc, argv, 0, 0, &arg_count); //第5项input, 会传递给回调函数的state->input
    43. }

    第6个参数你可以传递一个整数,也可以传递一个结构以包含更多信息.
    argp_failure 函数实际上类似于printf, 不过它有统一的,标准的外观和感觉.

    先介绍到这里吧.
    1.介绍了struct argp_option 及其6个成员.
    2.介绍了struct argp 7个成员中的3个成员
    3.介绍了argp_parse函数6个参数中的4个参数

    以后有需要再扩充:

    参考1: http://nongnu.askapache.com/argpbook/step-by-step-into-argp.pdf
    参考2: https://blog.csdn.net/sinat_38816924/article/details/122180938#t10 (对英文版的翻译)
    参考3: gnu 库代码

  • 相关阅读:
    【屏幕模块 - 笔记】深圳市晶联讯电子 液晶模块 JLX19296G-915-BN
    目前放疗中可用的一些开源软件
    音视频标签
    python 微信公众号,微信小程序wechatpy的使用
    使用查找表(LUT,Look-Up Table)来进行图像像素值的线性映射,图像对比度增强
    javascript中如何将多个数组的一个元素相加求和
    Python---类型注解
    ssm基于java的大学生成绩管理系统毕业设计源码130930
    RPA+ERP:5大优势与5个应用场景
    系列三、双亲委派机制
  • 原文地址:https://blog.csdn.net/hejinjing_tom_com/article/details/127444574