属性

Attribute & Reflection libraries for C++?

大多数成熟的C项目似乎都有自己的反射和属性系统,即用于定义可以通过字符串访问并可以自动序列化的属性。至少我参与的许多C项目似乎都是在重新发明轮子。

您是否知道C的任何良好的开源库,都支持反射和属性容器,特别是:

  • 通过宏定义RTTI和属性
  • 通过代码访问RTTI和属性
  • 自动序列化属性
  • 监听属性修改(例如OnValueChanged)

有一个新项目使用完全不同的方法在C中提供反射:CAMP。
https://github.com/tegesoft/camp

CAMP不使用预编译器,使用类似于boost.python或luabind的语法手动声明类/属性/函数/...。当然,如果愿意,人们可以使用gccxml或open-c之类的预编译器来生成此声明。

它仅基于纯C和boost头,并且由于模板元编程的强大功能,它支持任何类型的可绑定实体(例如,继承和奇怪的构造函数都不是问题)。

它是根据MIT许可(以前是LGPL)分发的。


这是C遇到反射时得到的结果:

C++ meets Reflection

无论您选择什么,它都可能具有可怕的宏,难以调试的代码或怪异的构建步骤。我已经看到一个系统从DevStudio的PDB文件自动生成序列化代码。

尽管如此,严重的是,对于小型项目,编写保存/加载函数(或使用流运算符)会更容易。实际上,这也可能适用于大型项目-很明显,这是怎么回事,而且如果结构发生更改,通常通常仍然需要更改代码。


您可以看看下面的两个工具。我从未使用过它们中的任何一个,所以我无法告诉您它们的实用性。

XRTTI:

Xrtti is a tool and accompanying C++ library which extends the standard runtime type system of C++ to provide a much richer set of reflection information about classes and methods to manipulate these classes and their members.

OpenC:

OpenC++ is C++ frontend library (lexer+parser+DOM/MOP) and source-to-source translator. OpenC++ enables development of C++ language tools, extensions, domain specific compiler optimizations and runtime metaobject protocols.


我看了很长时间这些东西,但它们往往很笨拙。它们可能会阻止您使用继承或使用奇怪的构造函数等。最后,它们最终负担过多,而不是带来麻烦。

这种公开我现在使用的成员的方法非常轻巧,例如,您可以浏览一个用于序列化的类或将所有名为" x"的字段设置为0。它也是静态确定的,因此非常快。无需担心库代码或代码源的任何层会干扰构建过程。它概括为嵌套类型的层次结构。

使用一些宏来设置编辑器,以自动编写其中的一些内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
struct point
{
     int x;
     int y;

     // add this to your classes
     template <typename Visitor>
     void visit(Visitor v)
     {
         v->visit(x,"x");
         v->visit(y,"y");
     }
};


/** Outputs any type to standard output in key=value format */
struct stdout_visitor
{
     template <typename T>
     void visit(const T& rhs)
     {
         rhs.visit(this);
     }

     template <typename Scalar>
     void visit (const Scalar& s, const char* name)
     {
          std::cout << name <<" =" << s <<"";
     }
}

也看了一会儿。当前最简单的解决方案似乎是BOOST_FUSION_ADAPT_STRUCT。实际上,一旦有了库/标题,您只需要将结构字段添加到BOOST_FUSION_ADAPT_STRUCT()宏中,如代码的最后一部分所示。是的,它有许多其他人提到的限制。而且它不直接支持侦听器。

我研究过的其他有希望的解决方案是

  • CAMP和XRTTI / gccxml似乎都是将外部工具依赖项引入项目的障碍。
  • 几年前,我使用perl c2ph / pstructgcc -gstabs的输出中转储元信息,虽然不那么麻烦,但需要更多的工作,尽管它对我来说非常有效。

关于boost / __ cxa方法,一旦找出所有小细节,添加/更改结构或字段就很容易维护。我们目前使用它在dbus之上构建自定义类型绑定层,以序列化API并隐藏托管对象服务子系统的传输/ RPC详细信息。


这通常是C语言一个臭名昭著的弱点,因为使反射实现可移植且值得进行的操作需要标准化的东西不是标准的。想到了调用约定,对象布局和符号修饰,但是还有其他一些。

标准缺乏指导,意味着编译器实现者将做一些不同的事情,这意味着很少有人有动力编写一个可移植的反射库,这意味着需要反射的人会重新发明轮子,但是仅够满足他们的需求。这是无限期发生的,到此为止。


不是一般的,但是QT通过元编译器支持此功能,并且是GPL。
通过与QT人员交谈,我的理解是,对于纯C而言这是不可能的,因此需要moc。


自动内省/反射工具包。使用Qt之类的元编译器,并将元信息直接添加到目标文件中。直观易用。没有外部依赖性。甚至允许自动反映std :: string,然后在脚本中使用它。请访问IDK


推荐阅读