我的C头文件包含大约300种各种函数,它们的名字都以" foo_db _"开头。并接受" db_t"作为他们的第一个参数(知道什么是db_t在这里没有真正相关,它只是一个结构)。
function foo_db_my_first_function(db_t *db, char *param1, int param2);
function foo_db_my_second_function(db_t *db, double param1, const char *param2, int param3);
(...)
function foo_db_my_Nth_function(db_t *db, int param1);
我的工作是编写另外300个包装函数,名为" foo_XXXX" (XXXX以" foo_db _"函数的后缀开头),并带有第一个参数的默认值。
static __inline function foo_my_first_function(char *param1, int param2) {
foo_db_my_first_function(DEFAULT_DB, param1, param2);
}
(...)
我想知道我是否可以编写一些宏来缓解我的工作:声明" db"功能和相应的"默认"功能(没有第一个参数)。
不幸的是,我不能使用C99和可变参数宏参数:( 所以我认为我已经搞砸了:),但我更喜欢先烧这里然后先烧掉我的手指来编写这300个函数:/
答案 0 :(得分:2)
假设API的原始头文件足够常规,那么您最喜欢的文本处理语言(Perl,Lua,Python,Awk甚至/ bin / sh中的脚本)可能是最简单的方法。
您的脚本将使用正则表达式或简单文本匹配来收集所有公共函数声明以识别它们(可能基于foo_db_
前缀)。然后它可以写两个输出文件。首先,一个合适的.h
文件声明你的包装器,第二个.c
源文件通过将DEFAULT_DB
填充到它们的第一个参数来实现它们。你需要做很少量的工作来复制其余的参数,但幸运的是,声明都足够常规,文本操作可以像“其余行”那样简单。
完成后,我会将脚本检查到版本控制,并在构建时调用它,将生成的文件视为瞬态构建产品。但是,如果你没有足够灵活的构建系统(这就是为什么我仍然将make
提供给我所见过的几乎所有其他东西)那么你将不得不找到一个合适的kludge来表示你生成的默认值API更改时,包装器已过期。
这种方法需要在代码生成器脚本中投入一些时间,但是在您想象手工编写第100个包装器之前,您应该在这方面做得更好。第二次你运行它....
在极端情况下,您最终可能需要实现C编译器的大部分前端。在这种情况下,我看到两种方法在社会上比在黑暗的小巷中安排与建筑师会面更容易接受。首先,有一个GCC后端以XML格式发出它的AST;生成的XML是一个熊,但已经减少到可以操作的令牌树。其次,总有LPeg,一个完整的解析器,很容易从Lua中使用(我怀疑其他的脚本语言也有其他的PEG解析器)。 lexes和parses C的LPeg示例代码为referenced at the Wiki page。
答案 1 :(得分:0)
在Excel中执行。使用" foo_db_(db_t * db)"创建一个单元格,将其拖动到所需的多个位置,填写所有空白,然后将其全部复制到您的程序中(您可以测试该副本将提前工作,但我只是尝试使用记事本,它似乎按预期工作)。现在你有了所有的函数头,并且可以从那里填写其余的函数。