#include <stdio.h>
#include <stdlib.h>
#include "metaresc.h"
TYPEDEF_STRUCT (sample_t,
int x,
float y,
string_t z
);
int main (int argc, char * argv[])
{
mr_td_t * tdp = mr_get_td_by_name ("sample_t");
if (NULL == tdp)
return (EXIT_FAILURE);
int i;
for (i = 0; i < tdp->fields_size / sizeof (tdp->fields[0]); ++i)
MR_PRINT ("offset [", tdp->fields[i].fdp->offset,
"] size ", tdp->fields[i].fdp->size,
" field '", tdp->fields[i].fdp->name.str,
"' type '", tdp->fields[i].fdp->type,
"' mr_type ", (mr_type_t, &tdp->fields[i].fdp->mr_type)
);
return (EXIT_SUCCESS);
}
此程序将输出
$ ./struct
offset [0] size 4 field 'x' type 'int' mr_type MR_TYPE_INT32
offset [4] size 4 field 'y' type 'float' mr_type MR_TYPE_FLOAT
offset [8] size 8 field 'z' type 'string_t' mr_type MR_TYPE_STRING
6条答案
按热度按时间xpszyzbs1#
以下是概念证明:
这是它的输出:
您可以对其进行改进,以更好地支持更复杂的成员类型,并实际构建成员名称列表。
q3aa05252#
绝对没有标准的方法。
如果你想编译代码两次,你可以只在第二次编译时启用预处理器定义 Package 代码路径,它从第一次编译产生的编译单元读取调试信息,以获取成员名称。你也可以在运行时分析源代码以获取列表。
最后,您可以使用预处理器宏来定义结构,并让宏在另一个变量中为每个结构成员发出一个条目,从而有效地使两个不直接相关的项保持同步。
u4vypkhs3#
查看Metaresc库https://github.com/alexanderchuranov/Metaresc
它为类型声明提供了接口,也为类型生成元数据。基于元数据,你可以轻松地序列化/反序列化任何复杂的对象。开箱即用,你可以序列化/反序列化XML,JSON,XDR,Lisp类符号,C-init符号。
下面是一个简单的例子:
此程序将输出
库对最新的gcc和clang工作正常。
lkaoscv74#
没有可移植的标准方法来实现这一点。上次我想解决一个类似的问题,我使用SWIG生成一些XML,然后处理这些XML以生成我想要的 meta信息。gcc-xml也可以做同样的事情。
vhmi4jdf5#
不,那不可能。
C是一种没有反射的静态类型语言。类型名在编译阶段之后没有任何意义,甚至在二进制代码中任何特定的变量都是不可见的。编译器有很大的自由来优化和重新排序,只要程序按照语言标准的描述运行。
您可以尝试一些预处理器魔法来获得类型名称的有限句柄,但这与一般反射相去甚远(严格地说,在C语言之外)。
在C语言中你不能做的主要事情是:
类型名 * 不是 * 运行时概念;更重要的是,静态类型使得任何这样的构造都不可能。
下面是我能想到的少数几个预处理器技巧之一:
7fhtutme6#
Qt扫描.h文件并生成.cpp,函数返回此类代码。
您也可以使用一组宏来实现这一点,但是您需要为每种类型手工编写宏