【问题标题】:Parse .h header files into c# data structures in runtime在运行时将 .h 头文件解析为 c# 数据结构
【发布时间】:2012-05-11 08:39:38
【问题描述】:

我正在尝试编写一个 C# 库来操作我的 C/C++ 头文件。我希望能够读取和解析头文件并在 C# 中操作函数原型和数据结构。由于#ifdefs 和类似的东西引起的所有代码分支,我试图避免编写 C 解析器。

我尝试过使用 EnvDTE,但找不到任何像样的文档。 任何想法我该怎么做?

编辑 - 谢谢你的回答......这里有一些关于我的项目的更多细节:我正在使用调试 API 为 Windows 编写一个类似 ptrace 的工具,这使我能够跟踪我已经编译的二进制文件并查看正在调用哪些 Windows API .我还想看看每次调用中给出了哪些参数以及给出了哪些返回值,所以我需要知道 API 的定义。我也想知道我自己的库的定义(因此,头解析方法)。我想到了3个解决方案: * 解析头文件 * 解析 PDB 文件(我使用 DIA SDK 编写了一个原型,但不幸的是,符号 PDB 仅包含有关 API 的一般信息,而不是带有参数和返回值的真实原型) * 爬取 MSDN 在线图书馆(自动或手动)

有没有更好的方法在 c# 中在运行时获取 windows API 和我的库的名称和类型?

【问题讨论】:

  • 不要,只是不要。不管你这样做的原因是什么:你做错了。除了也许,也许如果你正在编写一个词法分析器或解析器生成器,但你不必问这种问题
  • 我想不出任何其他方法从我的代码库中获取原型(我的一些测试环境/模糊测试需要它)。
  • 那么您应该阅读有关如何测试软件的内容。提示:这不是通过解析标题和输入随机数据。您可能希望创建仅使用标头并将随机数据输入到实现中的测试类(使用程序的语言,即 C++)。
  • 另外,你犯了经典的“XY 问题”错误:meta.stackexchange.com/questions/66377/what-is-the-xy-problem
  • 你一直在解释我做错了什么,但没有给出真正的答案......我有我选择这种方法的理由,你的答案不是很有帮助..

标签: c# c++ parsing compiler-construction compilation


【解决方案1】:

解析 C(甚至“只是”标题)很难;语言比人们记忆中的要复杂, 然后是预处理器,最后是解析的问题。 C++ 基本上包含了所有的 C,而这里的 C++11 问题更严重。

人们通常可以针对一组有限的输入破解 98% 的解决方案,通常使用 Perl 中的正则表达式或其他一些字符串破解。如果这对你有用,那很好。通常发生的情况是 2% 会导致被破解的解析器阻塞或产生错误的答案,然后您可以调试结果并手动破解 98% 的解决方案输出。

被黑的解决方案往往会在真正的头文件上失败,这似乎将怪异集中在宏和条件句中(有时甚至会在条件臂中混合 C 和 C++ 的不同方言)。以典型的 Microsoft .h 文件为例。这似乎是 OP 想要处理的。预处理解决了部分问题,现在您将遇到 C 和/或 C++ 的真正复杂性。即使经过预处理,你也不会得到真正头文件的 98% 解决方案;您需要 typedef,因此也需要名称和类型解析。您可能会“解析” FOO X;这告诉你 X 是 FOO 类型的……哎呀,那是什么?只有符号表才能确定。

GCCXML 为 C 的 GCC 方言做了所有这些预处理、解析和符号表构建。微软的方言不同,我不认为 GCCXML 可以处理它。

一个更通用的工具是我们的DMS Software Reengineering Toolkit,它的 C front end;还有一个C++ front end(是的,它们是不同的;C 和 C++ 绝对不是同一种语言)。这些处理各种 C 方言(正确配置时包括 MS 和 GCC),进行宏/条件扩展,构建 AST 和符号表(名称和类型解析是否正确)。

您可以通过爬取生成的符号表结构来添加自定义以提取您想要的信息。您必须将您想要的内容导出到 C#(例如生成您的 C# 类),因为 DMS 不是用 .net 语言实现的。

【讨论】:

    【解决方案2】:

    在最一般的情况下,头文件只能使用,不能转换。

    这是由于预处理器 (#define) 可能使用宏、结构常量的片段等,这些只有在上下文中使用时才有意义。

    例子

    • 宏中带有 ## 的任何内容

    //header
    #define mystructconstant "bla","bla"
    
    // in using .c
    char test[10][2] ={mystructconstant};
    

    但你不能简单地丢弃所有宏,因为这样你就不会处理非常常见的调用约定宏

    等等等等

    因此,标头解析和转换大多仅适用于半自动化使用(通过它手动运行清理的标头)或相当干净和一致的标头(例如较旧的 MS SDK 标头)

    由于一般情况非常困难,因此没有多少现成的。每个人都会为自己的标题制作一些又快又脏的东西。

    我知道的唯一更通用的工具是 SWIG。

    【讨论】:

    • 我正在使用带有 /EP 标志的 MSVC 的 cl.exe 来生成预处理后的头文件版本。这种方法确实简化了数据的解析。我还发现 gcc-xml 可以为标头编译生成 XML 输出。但我有一种感觉,一定有更好的方法......
    • 我不希望基于 GCC 的 GCCXML 解析 MS 标头,因为 Microsoft 使用了不同的暗角语法。
    • 预处理使它更容易,但结果通常是不完整的(如上面的“mystructconstant 将消失)。预处理修复了标题中的替换,但不是实现中的替换。
    猜你喜欢
    • 2012-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-22
    • 1970-01-01
    • 1970-01-01
    • 2021-04-17
    相关资源
    最近更新 更多