提取C结构体的字段

14 投票
7 回答
11202 浏览
提问于 2025-04-15 17:55

我经常需要用其他编程语言写代码,这些代码要和C语言的结构体(struct)进行交互。最常见的情况是用Python编写代码,使用structctypes模块。

通常,我会有一个包含结构体定义的.h文件,我需要手动阅读这些定义,并在我的Python代码中重复这些定义。这非常耗时间,也容易出错,而且当这些定义频繁变化时,保持两者的一致性就变得很困难。

有没有什么工具或库(不一定是C或Python)可以读取.h文件,并生成一个结构化的结构体及其字段的列表?我希望能写一个脚本,自动生成我的Python结构体定义,而不想处理任意的C代码。使用正则表达式大约能解决90%的问题,但剩下的10%就会让我头疼不已。

7 个回答

3

你可以看看 Swig 或者 SIP,它们可以为你生成接口代码,或者使用 ctypes

5

正则表达式在90%的情况下都能很好地工作,但在剩下的10%里却会让人头疼不已。

这些头疼的情况通常发生在你的C代码中出现了一些你在写正则表达式时没想到的语法。这时你会发现,C语言其实并不适合用正则表达式来解析,这样一来,事情就变得不那么有趣了。

不如换个思路:自己定义一个简单的格式,这个格式比C语言的规则要少一些,然后从这个文件生成C语言的头文件和Python接口代码:

define socketopts
    int16 port
    int32 ipv4address
    int32 flags

这样你就可以轻松写一些Python代码,把它转换成:

typedef struct {
    short port;
    int ipv4address;
    int flags;
} socketopts;

同时还可以生成一个Python类,这个类使用struct来打包和解包三个值(可能其中两个是大端格式,另一个是本地格式,具体由你决定)。

11

如果你在编译C代码的时候加上调试选项(-g),那么你可以使用这个工具(可以在这里找到,也可以在GitHub上查看)来获取你代码中使用的结构体的具体布局。

$ pahole /bin/dd
…
struct option {
        const char  *              name;                 /*     0     8 */
        int                        has_arg;              /*     8     4 */

        /* XXX 4 bytes hole, try to pack */

        int *                      flag;                 /*    16     8 */
        int                        val;                  /*    24     4 */

        /* size: 32, cachelines: 1, members: 4 */
        /* sum members: 24, holes: 1, sum holes: 4 */
        /* padding: 4 */
        /* last cacheline: 32 bytes */
};
…

这样获取的信息比直接从C代码中解析要简单很多。

撰写回答