C struct在运行时内省

时间:2015-01-09 21:48:51

标签: c introspection

C语言是否有允许运行时结构内省的工具?

上下文是这样的: 我有一个响应外部事件的守护进程,对于每个事件,我们都带有一个执行上下文结构(" context")。上下文很大且很混乱,并且包含对各种状态的引用。

一旦处理完事件,我希望能够通过过滤器运行上下文,如果它符合某些条件,则删除日志消息以帮助调试。但是,由于我希望将其用于现场调试,因此我不知道在运行时直到过滤有什么标准。

我理想的解决方案将允许用户基本上编写一个C风格的布尔表达式并让程序使用它。类似的东西:

activate_filter context.response_time > 4.2 && context.event.event_type == foo_event

迄今为止被抛弃的想法包括:

  • 提供我们知道如何访问的有限字段集。
  • 在运行时生成内省工具的某种宏中包装所有相关结构。
  • 编写一个知道哪里(版本化)标头存在的python脚本,生成C代码并将其编译为dll,然后守护进程加载并用作过滤器。显然,这种方法有一些额外的安全性考虑。

在我开始疯狂设计鹅追逐之前,有没有人知道这种野外的例子?我在谷歌上搜索了一些谷歌,但还没有想出什么。

3 个答案:

答案 0 :(得分:2)

我还建议从另一个角度解决这个问题。你问题中的关键词是:

  

背景大而混乱

这就是问题所在。清理完毕后,您可能会想出一个干净的日志工具。

请考虑以一种简单易用的格式重新定义上下文struct中的所有字段,例如XML。一个简单的`XML模式,列出结构的所有成员,它们的类型,以及一些其他元数据,甚至是记录该字段的注释。

然后,将一个快速而脏的样式表放在一起,该样式表读取XML文件并生成一个可编译的C结构,代码实际使用该结构。然后,一个不同的样式表,用于生成robo生成的代码,用于枚举结构中的每个字段,并生成将每个字段转换为字符串的代码。

由此,使用用户提供的过滤字符串对某种日志记录工具进行抽薹变得更容易。你必须想出一些解析任意过滤字符串的方法。了解lexyacc会派上用场。

之前已经完成了这种性质的事情。

XCB library是X11协议的C客户端库。该协议定义了各种二进制消息,这些消息本质上是客户端和服务器通过套接字相互折腾的简单struct。实现libxcb的方式是,所有X11消息及其中的所有数据类型都在XML定义中描述,样式表robo生成C结构定义,以及解析它们的代码,并提供相当干净的C API。解析并生成X11消息。

答案 1 :(得分:0)

你可能从错误的一方接近这个问题。

日志记录通常用于方便调试。该程序将各种事件写入日志文件。要提取有趣的条目,过滤将应用于日志文件。

有时程序会产生太多事件;日志库通常通过提供详细程度控制来解决此问题。基本上,日志记录功能需要一个额外的参数来告诉当前消息的详细程度。如果该值高于全局配置的阈值,则丢弃该消息。有些库甚至允许在每个模块的基础上控制详细级别(例如:谷歌日志)。

另一种可能的方法是利用调试器的强大功能,因为调试器可以访问各种元信息。可以在任意条件的范围内创建条件断点测试变量。一旦程序停止,可以从范围中提取任何信息。这可以使用调试器提供的脚本工具自动完成(gdb很棒)。

最后,有一些工具可以生成粘合代码,以便使用脚本语言中的C库。一个例子是SWIG。它分析头文件并生成允许脚本语言调用函数,访问结构字段等的代码。

您的过滤器表达式将成为Lua中的程序(也支持其他脚本语言)。您调用此程序将指针传递给执行上下文结构(“上下文”)。由于SWIG Lua程序生成的访问器可以检查结构中的任何字段。

答案 2 :(得分:0)

我从SWIG-CSV parser中产生了内省。

假设C代码包含如下结构,

class Bike {
public:
    int color;      // color of the bike
    int gearCount;      // number of configurable gear
    Bike() {
        // bla bla
    }
    ~Bike() {
        // bla bla
    }
    void operate() {
        // bla bla
    }
};

然后它将生成以下CSV元数据,

Bike|color|int|variable|public|
Bike|gearCount|int|variable|public|
Bike|operate|void|function|public|f().

现在,如果需要,可以使用python或C / C ++轻松解析CSV文件。

import csv
with open('bike.csv', 'rb') as csvfile:
    bike_metadata = csv.reader(csvfile, delimiter='|')
    # do your thing