参数解析库 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
这样的尾缀表达,开发起来友好不少。