赞
踩
我想使用过QT的同学会比较熟悉里面的一个概念"属性"Property。用过CEGUI的人也会发现里面有一个小型的“属性集”PropertySet。它们通常被集成在基础组件中,被用来做对象的属性设置接口,这套系统为配置文件和界面布局工具带来了便利。
- int value = 0;
- myType t;
- t.setValue("A", "123");
- t.getValue("A", &value);
以上就是较为常用的方式,通过字符串的设置,来将属性数值直接传递给对象。而屏蔽掉具体的类型。由于编辑器生成的配置文件是字符串序列,这样设计会方便整合。
我之前参考QT和CEGUI使用c++做过一个,但是模板套模板,看起来比较复杂。
后来使用c设计一个类似的组件,核心就两对文件,很好理解。
基本思路就是用一张表存储属性,属性可以绑定处理函数。通过转化类型来达成目的。尽量简洁设计,直接支持基础数据类型的转换,可以拓展数据类型。我们需要string和map来辅助实现。
https://bitbucket.org/mm_longcheng/mm-core/src/dev/mm/src/core/mmPropertySet.h
- struct myType
- {
- struct mmPropertySet s;
- int a;
- };
- void myType_Init(struct myType* p);
- void myType_Destroy(struct myType* p);
- void myType_SetValueA(struct myType* p, const int* value);
- void myType_GetValueA(const struct myType* p, int* value);
-
- void myType_Init(struct myType* p)
- {
- mmPropertySet_Init(&p->s);
- p->a = 0;
-
- static const char cOrigin[] = "myType";
- // bind object for this.
- mmPropertySet_SetObject(&p->s, p);
- // bind member property.
- mmPropertyDefine(&p->s,
- "A", struct myType,
- a, UInt, "0",
- &myType_SetValueA,
- &myType_GetValueA,
- cOrigin,
- "a value");
- }
- void myType_Destroy(struct myType* p)
- {
- p->a = 0;
- mmPropertySet_Destroy(&p->s);
- }
-
- void myType_SetValueA(struct myType* p, const int* value)
- {
- p->a = (*value);
- }
- void myType_GetValueA(const struct myType* p, int* value)
- {
- (*value) = p->a;
- }
-
- static void PropertySetFunc(void)
- {
- int value = 0;
- // weak string not need Allocator.
- struct mmString v;
- struct myType t;
- mmString_MakeWeak(&v, "123");
- myType_Init(&t);
- printf("a: %d\n", t.a);
- // a: 0
- mmPropertySet_SetValueString(&t.s, "A", &v);
- mmPropertySet_GetValueMember(&t.s, "A", &value);
- // a: 123 value: 123
- printf("a: %d value: %d\n", t.a, value);
- myType_Destroy(&t);
- }
- #include "core/mmString.h"
- #include "container/mmRbtreeString.h"
-
- #include "core/mmValueTransform.h"
-
- // mmString 是一个字符串组件.
- // 参考这篇文章 https://joellaity.com/2020/01/31/string.html
- //
- // mmRbtreeString 需要一个<字符串, void*>表
- // 参考 http://en.wikipedia.org/wiki/Rbtree
- // 以及linux rbtree.
- //
- // mmValueTransform 是一组字符串和基础类型互转的函数集合.
- struct mmProperty;
-
- // 字符串与类型之间的转换协议
- struct mmPropertyHelper
- {
- void(*SetValueString)(const struct mmProperty* p,
- void* obj, const struct mmString* pValue);
-
- void(*GetValueString)(const struct mmProperty* p,
- const void* obj, struct mmString* pValue);
- };
-
- // 属性的定义
- struct mmProperty
- {
- struct mmString hName;
- struct mmString hHelp;
- struct mmString hDefault;
- struct mmString hOrigin;
- size_t hMemberOffset;
- size_t hMemberLength;
- void* pSetterFunc;
- void* pGetterFunc;
- struct mmPropertyHelper hHelper;
- };
-
- // 属性集合,记录了<名字, 属性>的一张表
- struct mmPropertySet
- {
- struct mmRbtreeStringVpt rbtree;
- void* obj;
- };
- void mmPropertyHelper_SetValueStringUInt(const struct mmProperty* p, void* obj, const struct mmString* pValue)
- {
- typedef void(*SetterFuncType)(void* obj, const void* value);
- SetterFuncType hFunc = (SetterFuncType)(p->pSetterFunc);
- mmUInt_t hArgs = 0;
- const char* pString = mmString_CStr(pValue);
- mmValue_AToUInt(pString, &hArgs);
- assert(hFunc && "hFunc is invalid.");
- (*(hFunc))(obj, &hArgs);
- }
- void mmPropertyHelper_GetValueStringUInt(const struct mmProperty* p, const void* obj, struct mmString* pValue)
- {
- typedef void(*GetterFuncType)(const void* obj, void* value);
- GetterFuncType hFunc = (GetterFuncType)(p->pGetterFunc);
- mmUInt_t hArgs = 0;
- char pString[16] = { 0 };
- assert(hFunc && "hFunc is invalid.");
- (*(hFunc))(obj, &hArgs);
- mmValue_UIntToA(hArgs, pString);
- mmString_Appends(pValue, pString);
- }
- MM_EXPORT_DLL const struct mmPropertyHelper mmPropertyHelperUInt =
- {
- &mmPropertyHelper_SetValueStringUInt,
- &mmPropertyHelper_GetValueStringUInt,
- };
- // 定义一个void*的成员用于存储绑定的函数
- void* pSetterFunc;
-
- // 实际需要被绑定的函数,注意参数是以常用函数的形式定义的
- void myType_SetValueA(struct myType* p, const int* value);
-
- // 函数的绑定
- pSetterFunc = &myType_SetValueA;
-
- // 函数的使用,注意我们定义了一个(void*, const void*)的泛型函数
- typedef void(*SetterFuncType)(void* obj, const void* value);
- SetterFuncType hFunc = (SetterFuncType)(p->pSetterFunc);
- // 在cpu将参数压入栈中时,数据位宽合规,是安全的,最终正常触发绑定函数,达到泛型
- (*(hFunc))(obj, pValue);
-
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。