当前位置:   article > 正文

组件:c语言版本属性集PropertySet_c语言property_set

c语言property_set

背景介绍

我想使用过QT的同学会比较熟悉里面的一个概念"属性"Property。用过CEGUI的人也会发现里面有一个小型的“属性集”PropertySet。它们通常被集成在基础组件中,被用来做对象的属性设置接口,这套系统为配置文件和界面布局工具带来了便利

  1. int value = 0;
  2. myType t;
  3. t.setValue("A", "123");
  4. t.getValue("A", &value);

以上就是较为常用的方式,通过字符串的设置,来将属性数值直接传递给对象。而屏蔽掉具体的类型。由于编辑器生成的配置文件是字符串序列,这样设计会方便整合。

我之前参考QT和CEGUI使用c++做过一个,但是模板套模板,看起来比较复杂。

后来使用c设计一个类似的组件,核心就两对文件,很好理解

基本思路就是用一张表存储属性,属性可以绑定处理函数。通过转化类型来达成目的。尽量简洁设计,直接支持基础数据类型的转换,可以拓展数据类型。我们需要string和map来辅助实现。

1.最终使用案例

https://bitbucket.org/mm_longcheng/mm-core/src/dev/mm/src/core/mmPropertySet.h

  1. struct myType
  2. {
  3. struct mmPropertySet s;
  4. int a;
  5. };
  6. void myType_Init(struct myType* p);
  7. void myType_Destroy(struct myType* p);
  8. void myType_SetValueA(struct myType* p, const int* value);
  9. void myType_GetValueA(const struct myType* p, int* value);
  10. void myType_Init(struct myType* p)
  11. {
  12. mmPropertySet_Init(&p->s);
  13. p->a = 0;
  14. static const char cOrigin[] = "myType";
  15. // bind object for this.
  16. mmPropertySet_SetObject(&p->s, p);
  17. // bind member property.
  18. mmPropertyDefine(&p->s,
  19. "A", struct myType,
  20. a, UInt, "0",
  21. &myType_SetValueA,
  22. &myType_GetValueA,
  23. cOrigin,
  24. "a value");
  25. }
  26. void myType_Destroy(struct myType* p)
  27. {
  28. p->a = 0;
  29. mmPropertySet_Destroy(&p->s);
  30. }
  31. void myType_SetValueA(struct myType* p, const int* value)
  32. {
  33. p->a = (*value);
  34. }
  35. void myType_GetValueA(const struct myType* p, int* value)
  36. {
  37. (*value) = p->a;
  38. }
  39. static void PropertySetFunc(void)
  40. {
  41. int value = 0;
  42. // weak string not need Allocator.
  43. struct mmString v;
  44. struct myType t;
  45. mmString_MakeWeak(&v, "123");
  46. myType_Init(&t);
  47. printf("a: %d\n", t.a);
  48. // a: 0
  49. mmPropertySet_SetValueString(&t.s, "A", &v);
  50. mmPropertySet_GetValueMember(&t.s, "A", &value);
  51. // a: 123 value: 123
  52. printf("a: %d value: %d\n", t.a, value);
  53. myType_Destroy(&t);
  54. }

2.前置数据结构组件

  1. #include "core/mmString.h"
  2. #include "container/mmRbtreeString.h"
  3. #include "core/mmValueTransform.h"
  4. // mmString 是一个字符串组件.
  5. // 参考这篇文章 https://joellaity.com/2020/01/31/string.html
  6. //
  7. // mmRbtreeString 需要一个<字符串, void*>表
  8. // 参考 http://en.wikipedia.org/wiki/Rbtree
  9. // 以及linux rbtree.
  10. //
  11. // mmValueTransform 是一组字符串和基础类型互转的函数集合.

3.主要数据结构

  1. struct mmProperty;
  2. // 字符串与类型之间的转换协议
  3. struct mmPropertyHelper
  4. {
  5. void(*SetValueString)(const struct mmProperty* p,
  6. void* obj, const struct mmString* pValue);
  7. void(*GetValueString)(const struct mmProperty* p,
  8. const void* obj, struct mmString* pValue);
  9. };
  10. // 属性的定义
  11. struct mmProperty
  12. {
  13. struct mmString hName;
  14. struct mmString hHelp;
  15. struct mmString hDefault;
  16. struct mmString hOrigin;
  17. size_t hMemberOffset;
  18. size_t hMemberLength;
  19. void* pSetterFunc;
  20. void* pGetterFunc;
  21. struct mmPropertyHelper hHelper;
  22. };
  23. // 属性集合,记录了<名字, 属性>的一张表
  24. struct mmPropertySet
  25. {
  26. struct mmRbtreeStringVpt rbtree;
  27. void* obj;
  28. };

4.主要处理函数,取其中一种。

  1. void mmPropertyHelper_SetValueStringUInt(const struct mmProperty* p, void* obj, const struct mmString* pValue)
  2. {
  3. typedef void(*SetterFuncType)(void* obj, const void* value);
  4. SetterFuncType hFunc = (SetterFuncType)(p->pSetterFunc);
  5. mmUInt_t hArgs = 0;
  6. const char* pString = mmString_CStr(pValue);
  7. mmValue_AToUInt(pString, &hArgs);
  8. assert(hFunc && "hFunc is invalid.");
  9. (*(hFunc))(obj, &hArgs);
  10. }
  11. void mmPropertyHelper_GetValueStringUInt(const struct mmProperty* p, const void* obj, struct mmString* pValue)
  12. {
  13. typedef void(*GetterFuncType)(const void* obj, void* value);
  14. GetterFuncType hFunc = (GetterFuncType)(p->pGetterFunc);
  15. mmUInt_t hArgs = 0;
  16. char pString[16] = { 0 };
  17. assert(hFunc && "hFunc is invalid.");
  18. (*(hFunc))(obj, &hArgs);
  19. mmValue_UIntToA(hArgs, pString);
  20. mmString_Appends(pValue, pString);
  21. }
  22. MM_EXPORT_DLL const struct mmPropertyHelper mmPropertyHelperUInt =
  23. {
  24. &mmPropertyHelper_SetValueStringUInt,
  25. &mmPropertyHelper_GetValueStringUInt,
  26. };

5.原理

  1. // 定义一个void*的成员用于存储绑定的函数
  2. void* pSetterFunc;
  3. // 实际需要被绑定的函数,注意参数是以常用函数的形式定义的
  4. void myType_SetValueA(struct myType* p, const int* value);
  5. // 函数的绑定
  6. pSetterFunc = &myType_SetValueA;
  7. // 函数的使用,注意我们定义了一个(void*, const void*)的泛型函数
  8. typedef void(*SetterFuncType)(void* obj, const void* value);
  9. SetterFuncType hFunc = (SetterFuncType)(p->pSetterFunc);
  10. // 在cpu将参数压入栈中时,数据位宽合规,是安全的,最终正常触发绑定函数,达到泛型
  11. (*(hFunc))(obj, pValue);

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/249745
推荐阅读
相关标签
  

闽ICP备14008679号