参数解析库 argtable2 的使用
Contents
C 程序解析命令行参数一般都会使用 getopt/getoptlong 这两个 GNU 接口,简单的参数设计还好,稍微复杂的就会维护起来很麻烦,比如手写 usage、命令参数的分散性(参数的异常处理)等等。
argtable2 是一个底层基于 getopt 的命令行参数处理库,开源协议为 LGPL, 使用它开发复杂命令行接口简单且易于维护。
argtable2 在设计上,是面向参数本身,与该参数有关的信息都会汇聚在一起,成为一个 arg 对象。也就是说,该参数的特性,以及其 usage 都是在一起的,这对于开发和维护会特别方便(相对于基础的 getopt 而言)。
先来一个实际代码示例:
|
|
其中的核心设计就是 struct arg_xxx 系列的对象,用于存储参数的类型(literal/int/double/str/date 等)、短标识(比如 -v)、长标识(比如 --version)、参数表征类型(比如 <device>)、参数说明。因为 argtable 支持多次参数设置,所以还包含一个参数数量。
arg_lit0/arg_str0 这样的函数,用来初始化参数对象,其中 lit 代表无类型参数,比如 -v 这些,后面的数字代表参数的出现次数,0 类似正则中的 ?,即 0 或者 1次,而 1 代表必须 1 次,而 n 则代表可出现1次或多次。arg_end 是一个特殊对象,用来存储参数解析的异常情况,arg_end(X) 的参数代表可以存储最多多少个错误信息。
在解析时,则需要将各个参数对象放置到一个 argtable 中,然后利用 arg_nullcheck 和 arg_parse 去初始化和解析参数。
对于 usage 打印,可以使用 arg_print_syntaxv 这样的接口,这个接口会打印精简的命令行帮助,而 arg_print_glossary 则可以打印表格样式的命令行帮助:
|
|
而对于参数的处理上,使用对应参数对象的 count 属性,来判断参数出现的次数,进而取值进行处理。需要注意的是,参数对象的值只在 arg_freetable 前生存有效,使用时需要注意生命周期管理。
不过对于程序而言,有时为了方便,可以不考虑调用 arg_freetable,毕竟程序结束时系统会进行回收,而参数处理,只有在程序运行时才执行1次而已,在程序运行期间保有这部分资源也还好。
如果参数对象需要设置默认参数值,则需要在 arg_nullcheck 后 arg_parse 前对字段进行赋值。
argtable2 本身底层仍然是调用 getopt 接口实现的,不过这种基于参数对象的管理设计,对于维护性有很大的提升,有时候,手写复杂的 getopt 太琐碎了。而且,argtable2 还支持 date 这样类型的参数处理,以及 kb/mb/gb 这样的尾缀表达,开发起来友好不少。