免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 5248 | 回复: 7

[C] 想用宏来实现C语言结构体的简单反射功能 [复制链接]

论坛徽章:
36
CU大牛徽章
日期:2013-09-18 15:24:20NBA常规赛纪念章
日期:2015-05-04 22:32:03牛市纪念徽章
日期:2015-07-24 12:48:5515-16赛季CBA联赛之辽宁
日期:2016-03-30 09:26:4715-16赛季CBA联赛之北控
日期:2016-03-30 11:26:2315-16赛季CBA联赛之广夏
日期:2016-05-20 15:46:5715-16赛季CBA联赛之吉林
日期:2016-05-24 11:38:0615-16赛季CBA联赛之青岛
日期:2016-05-30 13:41:3215-16赛季CBA联赛之同曦
日期:2016-06-23 16:41:052015年亚洲杯之巴林
日期:2015-02-03 15:05:04CU大牛徽章
日期:2013-09-18 15:24:52CU十二周年纪念徽章
日期:2013-10-24 15:46:53
发表于 2015-12-08 11:34 |显示全部楼层
可行吗?
有没有什么思路或者例子?

论坛徽章:
3
2015年迎新春徽章
日期:2015-03-04 09:56:11数据库技术版块每日发帖之星
日期:2016-08-03 06:20:00数据库技术版块每日发帖之星
日期:2016-08-04 06:20:00
发表于 2015-12-08 12:16 |显示全部楼层
都C了,还反射个啥啊,折腾

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
发表于 2015-12-13 20:16 |显示全部楼层
本帖最后由 yulihua49 于 2015-12-13 20:27 编辑
idi0t 发表于 2015-12-08 11:34
可行吗?
有没有什么思路或者例子?

这个最近讨论的比较多,大都不了了之。问一下windoz大侠。
http://bbs.chinaunix.net/thread-4192445-1-1.html
http://bbs.chinaunix.net/forum.p ... ;page=3#pid24476006
http://bbs.chinaunix.net/thread-4190378-1-1.html     C++的
只有我是C的,结构的反射替代方案---结构映射。
http://blog.chinaunix.net/uid-8804348-id-2013147.html

论坛徽章:
89
水瓶座
日期:2014-04-01 08:53:31天蝎座
日期:2014-04-01 08:53:53天秤座
日期:2014-04-01 08:54:02射手座
日期:2014-04-01 08:54:15子鼠
日期:2014-04-01 08:55:35辰龙
日期:2014-04-01 08:56:36未羊
日期:2014-04-01 08:56:27戌狗
日期:2014-04-01 08:56:13亥猪
日期:2014-04-01 08:56:02亥猪
日期:2014-04-08 08:38:58程序设计版块每日发帖之星
日期:2016-01-05 06:20:00程序设计版块每日发帖之星
日期:2016-01-07 06:20:00
发表于 2015-12-13 21:09 |显示全部楼层
C跟C++的痛点,嘿嘿嘿嘿。

论坛徽章:
36
CU大牛徽章
日期:2013-09-18 15:24:20NBA常规赛纪念章
日期:2015-05-04 22:32:03牛市纪念徽章
日期:2015-07-24 12:48:5515-16赛季CBA联赛之辽宁
日期:2016-03-30 09:26:4715-16赛季CBA联赛之北控
日期:2016-03-30 11:26:2315-16赛季CBA联赛之广夏
日期:2016-05-20 15:46:5715-16赛季CBA联赛之吉林
日期:2016-05-24 11:38:0615-16赛季CBA联赛之青岛
日期:2016-05-30 13:41:3215-16赛季CBA联赛之同曦
日期:2016-06-23 16:41:052015年亚洲杯之巴林
日期:2015-02-03 15:05:04CU大牛徽章
日期:2013-09-18 15:24:52CU十二周年纪念徽章
日期:2013-10-24 15:46:53
发表于 2015-12-14 08:57 |显示全部楼层
回复 3# yulihua49


    这几次尝试着去实现一个简单的例子,发现不好实现,而且不论看上去还有实现上都觉得好丑陋,
    位域,结构体的支持这些想不到好办法。看来真是瞎折腾。C语言还是简单就好吧。
    packet.h:
  1. #ifndef _HAVE_PACKET_H
  2. #define _HAVE_PACKET_H

  3. #include <stddef.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. enum field_class {
  8.     base,
  9.     packet,
  10.     array,
  11.     bits,
  12.     bit,
  13.     N_FIELD_CLASS
  14. };

  15. struct packet_desc {
  16.     char const *pkt_name;
  17.     size_t pkt_size;
  18.     size_t packed_size;
  19.     size_t n_fields;

  20.     size_t *field_offsets;
  21.     size_t *field_sizes;
  22.     size_t *field_class;
  23.     char const **field_names;
  24.     char const **field_types;
  25. };

  26. /* _ inner-define
  27. * */
  28. #define _DEFINE_base( type, name, size)  type name;
  29. #define _DEFINE_ref(  type, name, size)  type name;
  30. #define _DEFINE_array(type, name, size)  type name[size];
  31. #define _DEFINE_bit(  type, name, size)  type name:size;
  32. #define _DEFINE_bits( type, name, size)  \
  33.         struct {\
  34.             name(DEFINE) \
  35.         }name;
  36. #define _DEFINE_packet(type, name, size) \
  37.     struct name { \
  38.         name(DEFINE) \
  39.     }name;

  40. #define _SIZEOF_END(type, name, size) name),
  41. #define SIZEOF_END(name) _SIZEOF_END
  42. #define _SIZEOF_FIELD(name) sizeof(((struct name*)0)-> SIZEOF_END

  43. #define _COUNT_FIELD( type, name, size) +1
  44. #define _PACKED_END(type, name, size) name)
  45. #define PACKED_END(name) _PACKED_END
  46. #define _PACKED_FIELD(name) +sizeof(((struct name*)0)-> PACKED_END
  47. #define _STRING_TYPE( type, name, size) #type,
  48. #define _STRING_NAME( type, name, size) #name,
  49. #define _NULL_FIELD(  type, name, size)
  50. #define _OFFSET_END(  type, name, size) name),
  51. #define OFFSET_END(name) _OFFSET_END
  52. #define _OFFSET_FIELD(name) __builtin_offsetof(struct name, OFFSET_END

  53. #define DEFINE(CLASS)       _DEFINE_##CLASS
  54. #define COUNT_FIELD(CLASS)  _COUNT_FIELD
  55. #define SIZEOF_FIELD(CLASS) _SIZEOF_FIELD(CLASS)
  56. #define PACKED_FIELD(CLASS) _PACKED_FIELD(CLASS)
  57. #define STRING_TYPE(CLASS)  _STRING_TYPE
  58. #define STRING_NAME(CLASS)  _STRING_NAME
  59. #define CLASS_FIELD(CLASS)  CLASS,_NULL_FIELD
  60. #define OFFSET_FIELD(CLASS) _OFFSET_FIELD(CLASS)

  61. #define PACKET(name) \
  62.     struct name{ \
  63.         name(DEFINE) \
  64.     }; \
  65. struct packet_desc name##_desc = { \
  66.     .pkt_name       = #name, \
  67.     .pkt_size       = sizeof(struct name),\
  68.     .n_fields       = name(COUNT_FIELD),\
  69.     .packed_size    = name(PACKED_FIELD(name)),\
  70.     .field_offsets  = (size_t[])      { name(OFFSET_FIELD(name))},\
  71.     .field_sizes    = (size_t[])      { name(SIZEOF_FIELD(name)) },\
  72.     .field_class    = (size_t[])      { name(CLASS_FIELD) },\
  73.     .field_types    = (char const *[]){ name(STRING_TYPE) },\
  74.     .field_names    = (char const *[]){ name(STRING_NAME) },\
  75. };

  76. static inline void define_printf(struct packet_desc *desc)
  77. {
  78.     size_t n_field = 0;
  79.     printf("struct %s {\n", desc->pkt_name);
  80.     for (n_field = 0; n_field < desc->n_fields; n_field++) {
  81.         printf("\t%-16s%16s;\t/*%4d%4d */\n",
  82.                 desc->field_types[n_field],
  83.                 desc->field_names[n_field],
  84.                 desc->field_offsets[n_field],
  85.                 desc->field_sizes[n_field]
  86.                 );
  87.     }
  88.     printf("\n\t/* size: %d, members: %d */\n"
  89.            "\t/* sum members: %d */\n",
  90.            desc->pkt_size,
  91.            desc->n_fields,
  92.            desc->packed_size);
  93.     printf("};\n");
  94. }

  95. #endif /* _HAVE_PACKET_H */
复制代码
test.c:
  1. #include <stdio.h>
  2. #include <stdint.h>
  3. #include "packet.h"

  4. #define s(_) \
  5.     _(base)(int, hh, -)\
  6.     _(base)(int, jj, -)\
  7.     _(base)(int, kk, -)

  8. PACKET(s)

  9. #define world(_) \
  10.     _(bit)(int, bita, 4) \
  11.     _(bit)(int, bitb, 4) \
  12.     _(bit)(int, bitc, 28)\
  13.     _(bit)(int, bitd, 4)

  14. #define sub(_) \
  15.     _(base)(int, hh, -)\
  16.     _(base)(int, jj, -)\
  17.     _(base)(int, kk, -)

  18. #define hello(_) \
  19.     _(base)(int,   a, -) \
  20.     _(base)(short, b, -) \
  21.     _(bits)(struct,world, -) \
  22.     _(packet)(struct sub, sub, -) \
  23.     _(base)(struct s*, ha, -) \
  24.     _(array)(int,  c, 12)

  25. PACKET(hello)

  26. int main(void)
  27. {
  28.     struct hello hello;
  29.     define_printf(&hello_desc);
  30.     define_printf(&s_desc);
  31. }
  32. #undef s
  33. #undef world
  34. #undef hello

复制代码

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
发表于 2015-12-14 10:26 |显示全部楼层
idi0t 发表于 2015-12-14 08:57
回复 3# yulihua49

如果合用,就用着好了。
如果有更多的需求,再讨论。
我的方案,用于任意结构的序列化/反序列化,和, 读写数据库(映像式)。
主要效果是“柔性编程”,就是,数据结构的变化,程序不变化或少变化。

论坛徽章:
36
CU大牛徽章
日期:2013-09-18 15:24:20NBA常规赛纪念章
日期:2015-05-04 22:32:03牛市纪念徽章
日期:2015-07-24 12:48:5515-16赛季CBA联赛之辽宁
日期:2016-03-30 09:26:4715-16赛季CBA联赛之北控
日期:2016-03-30 11:26:2315-16赛季CBA联赛之广夏
日期:2016-05-20 15:46:5715-16赛季CBA联赛之吉林
日期:2016-05-24 11:38:0615-16赛季CBA联赛之青岛
日期:2016-05-30 13:41:3215-16赛季CBA联赛之同曦
日期:2016-06-23 16:41:052015年亚洲杯之巴林
日期:2015-02-03 15:05:04CU大牛徽章
日期:2013-09-18 15:24:52CU十二周年纪念徽章
日期:2013-10-24 15:46:53
发表于 2015-12-14 13:38 |显示全部楼层
回复 6# yulihua49


    你那个我之前想试下,但不支持位域啊

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
发表于 2015-12-14 19:29 |显示全部楼层
本帖最后由 yulihua49 于 2015-12-14 19:34 编辑
idi0t 发表于 2015-12-14 13:38
回复 6# yulihua49

位域是不支持。这个研究过一阵。每个CPU,每个编译器,对于位域的排列方法都不同,没有标准,所以做不了。
你用宏,可能能做,但是这个结构传到另一台机器,或者通过数据库在其他节点存取,不能保证一致。
最好使用整数,自己用移位操作解决。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP