【问题标题】:Extract the fields of a C struct提取 C 结构的字段
【发布时间】:2011-01-04 06:03:50
【问题描述】:

我经常不得不用其他语言编写与 C 结构交互的代码。最典型的是,这涉及使用 structctypes 模块编写 Python 代码。

所以我将拥有一个包含结构定义的 .h 文件,我必须手动阅读它们并在我的 Python 代码中复制这些定义。这既费时又容易出错,而且当两个定义频繁更改时,很难保持它们同步。

是否有任何语言(不必是 C 或 Python)的工具或库可以获取 .h 文件并生成其结构及其字段的结构化列表?我希望能够编写一个脚本来生成我在 Python 中自动生成的结构定义,并且我不想处理任意 C 代码来完成它。正则表达式在大约 90% 的时间里都可以很好地工作,然后在剩下的 10% 的时间里导致无穷无尽的头痛。

【问题讨论】:

  • "正则表达式在大约 90% 的时间里都可以很好地工作,然后对剩下的 10% 造成无休止的头痛。"是正则表达式的一个很好的总结。除了我会做出大约 50/50 的比率。

标签: python c language-agnostic struct


【解决方案1】:

如果您通过调试 (-g) 编译 C 代码,pahole (git) 可以为您提供所使用的确切结构布局。

$ pahole /bin/dd … 结构选项 { 常量字符 * 名称; /* 0 8 */ int has_arg; /* 8 4 */ /* XXX 4字节空洞,尝试打包 */ 整数 * 标志; /* 16 8 */ 整数值; /* 24 4 */ /* 大小:32,缓存线:1,成员:4 */ /* 和成员:24,孔:1,和孔:4 */ /* 填充:4 */ /* 最后一个缓存行:32 字节 */ }; …

这应该比直接的 C 更好解析。

【讨论】:

    【解决方案2】:

    正则表达式在大约 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 来打包/解包三个值(可能其中两个是 big-endian,另一个是 native-endian,由您决定)。

    【讨论】:

    • 我确实考虑过这一点,但我们经常收到来自其他公司的代码,我们需要实现自定义协议来与之通信,因为我们无法重写他们的代码但可以访问他们的头文件,这种方法是不可行的。但是,如果我自己从头开始实现一个同时包含 C 和 Python 组件的系统,我肯定会这样做。
    • 另外,我刚刚注意到我的示例仍然很糟糕,因为 Python 代码需要考虑“port”和“ipv4address”之间的平台相关填充。您也许可以通过使用此方案来解决“容易出错”的问题,手动将标头转换为 DSL,然后通过编写特定值自动生成一些测试(用 C 编写),以确保您的结构和原始结构相同到两个结构的各个字段,然后对它们进行内存管理。然后以同样的方式测试 Python 代码。如果所有匹配,你很好。
    • ...如果您的第三方向您发送了一个您无法翻译成您的 DSL 的头文件,那么要么扩展 DSL,要么抱怨 ;-) 但我更喜欢 ehemient 的回答,它是有约束力的工作量要少得多,因为所有填充信息都是直接从编译器中提取的。
    【解决方案3】:

    查看SwigSIP,它们将为您生成接口代码或使用ctypes

    【讨论】:

      【解决方案4】:

      你看过Swig吗?

      【讨论】:

        【解决方案5】:

        我已经在相当大的项目上成功地使用了GCCXML。您将获得 C 代码(包括结构)的 XML 表示,您可以使用一些简单的 Python 对其进行后处理。

        【讨论】:

          【解决方案6】:

          ctypes-codegenctypeslib(我认为同样的事情)将通过使用 GCCXML 解析头文件来生成 ctypes Structure 定义(我相信还有其他东西,但我只尝试过结构)。它不再受支持,但在某些情况下可能会起作用。

          【讨论】:

            【解决方案7】:

            我的一个朋友完成了这项任务,他使用 cog 完成了 C-parser。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2019-01-02
              • 1970-01-01
              • 2013-11-05
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-03-19
              相关资源
              最近更新 更多