如何在Python中获取C文件的变量名列表
我有一个C语言的文件,想用Python来创建一个所有定义的变量名的列表。
比如,从下面这个C语言文件:
int mynum = 12;
// Timers
VAR_IN_SECTION(task_timers, .mem_layout)
timers_t timers[DSP_NUM_TASK_TIMERS];
我希望能用一些Python的“魔法”来返回:
["mynum", "timers"]
这该怎么做呢?希望这个方法不局限于良好的C语言格式。用什么样的Python“魔法”可以实现呢?
注意:这个是用来解析一个只包含变量声明的文件。
2 个回答
这个在你给的示例输入文件上是有效的,但我敢肯定,在我说它能在C语言的语法上普遍适用之前,我需要进行很多更多的测试。
>>> s = """int mynum = 12;
...
... // Timers
... VAR_IN_SECTION(task_timers, .mem_layout)
... timers_t timers[DSP_NUM_TASK_TIMERS];"""
>>>
>>> import re
>>> re.findall(r'\w+[ \t]+(\w+)',s)
['mynum', 'timers']
上面提到的答案不能识别指针:
int *p;
为了能识别指针,可能需要稍微调整一下正则表达式:
>>> re.findall(r'\w+[ \t]+(?:\*\s*)?(\w+)',s)
['mynum', 'timers', 'p']
在C语言中,你不能只查找各种类型(比如int
、float
、double
、char
等),因为这些类型可以被重新定义(typedef),而且你还有struct
(和union
?)这样的结构,它们的工作方式也类似……更不用说在任何时候,你都可以用#include "anyfile.c"
来包含其他文件——作为程序员,这样做可能会很麻烦,但确实是可能的。我认为在c99
标准中,你还可以在任何地方声明变量(例如,在宏中)。你想要识别这些吗?换句话说,要正确处理这个问题,你需要一个完整的C语言解析器来帮你完成这些复杂的工作。
你可以使用GCC-XML这个工具,把C语言源文件中的声明转换成XML格式。然后,你可以用Python的XML解析器(比如lxml.etree
)来处理这些结果。
GCC-XML生成的XML结构比较简单,容易解析。它会给你提供变量声明(标签:<Variable>
)和类型定义(有多个标签,比如<FundamentalType>
、<Pointer>
、<Struct>
等等)。你需要做一些处理,递归地推导出实际的类型(例如,Pointer
指向一个子类型,也就是它所指向的类型),但如果你愿意花点时间去研究,它会提供你所需的一切。
如果你只想要变量名,可以解析XML,找到Variable
标签,然后提取它的name
属性。
有趣的是,我正在一个项目中构建这样一个解析器。虽然我现在还不能分享,但我希望最终能开源发布。
示例:
typedef int* myintptr;
myintptr p;
生成的XML大概是这样的:
<Variable id="_3" name="p" type="_64" context="_1" location="f0:5" file="f0" line="5"/>
<Typedef id="_64" name="myintptr" type="_63" context="_1" location="f0:3" file="f0" line="3"/>
<PointerType id="_63" type="_156" size="64" align="64"/>
<FundamentalType id="_156" name="int" size="32" align="32"/>