libvirt里的面向对象的C语言
C语言:类的声明和定义
1 // 通用父类的定义 2 struct _virClass { 3 virClassPtr parent; 4 5 unsigned int magic; 6 char *name; 7 size_t objectSize; 8 9 virObjectDisposeCallback dispose; 10 }; 11 typedef struct _virClass virClass; 12 typedef virClass *virClassPtr; 13 14 //通用对象的定义 15 struct _virObject { 16 /* Ensure correct alignment of this and all subclasses, even on 17 * platforms where 'long long' or function pointers have stricter 18 * requirements than 'void *'. */ 19 union { 20 long long dummy_align1; 21 void (*dummy_align2) (void); 22 struct { 23 unsigned int magic; 24 int refs; 25 } s; 26 } u; 27 virClassPtr klass; 28 }; 29 30 struct _virObjectLockable { 31 virObject parent; 32 virMutex lock; 33 }; 34 35 // 各个子类的声明与类对象指针的实例化 36 static int 37 virDataTypesOnceInit(void) 38 { 39 #define DECLARE_CLASS_COMMON(basename, parent) \ 40 if (!(basename ## Class = virClassNew(parent, \ 41 #basename, \ 42 sizeof(basename), \ 43 basename ## Dispose))) \ 44 return -1; 45 #define DECLARE_CLASS(basename) \ 46 DECLARE_CLASS_COMMON(basename, virClassForObject()) 47 #define DECLARE_CLASS_LOCKABLE(basename) \ 48 DECLARE_CLASS_COMMON(basename, virClassForObjectLockable()) 49 50 DECLARE_CLASS_LOCKABLE(virConnect); 51 DECLARE_CLASS_LOCKABLE(virConnectCloseCallbackData); 52 DECLARE_CLASS(virDomain); 53 DECLARE_CLASS(virDomainSnapshot); 54 DECLARE_CLASS(virInterface); 55 DECLARE_CLASS(virNetwork); 56 DECLARE_CLASS(virNodeDevice); 57 DECLARE_CLASS(virNWFilter); 58 DECLARE_CLASS(virSecret); 59 DECLARE_CLASS(virStream); 60 DECLARE_CLASS(virStorageVol); 61 DECLARE_CLASS(virStoragePool); 62 63 DECLARE_CLASS_LOCKABLE(virAdmConnect); 64 DECLARE_CLASS_LOCKABLE(virAdmConnectCloseCallbackData); 65 DECLARE_CLASS(virAdmServer); 66 DECLARE_CLASS(virAdmClient); 67 68 #undef DECLARE_CLASS_COMMON 69 #undef DECLARE_CLASS_LOCKABLE 70 #undef DECLARE_CLASS 71 72 return 0; 73 } 74 //定义这些指针的用途就是后续需要创建子类的对象是作为类型参数传入,用来区分不同的对象实例。同时,也是最主要的,指定了子类的对象的内存分配大小。
C语言:按一个对象类型来new一个对象实例
1 // 类似C++的new操作运算符。oh, my gold! 2 void *virObjectNew(virClassPtr klass) 3 { 4 // 声明父类指针,多态的开始么。。。 5 virObjectPtr obj = NULL; 6 // VIR_ALLOC_VAR 分配的内存大小为子类大小,指针的起始位置指向父类对象。 7 if (VIR_ALLOC_VAR(obj, 8 char, 9 klass->objectSize - sizeof(virObject)) < 0) 10 return NULL; 11 // 因为是C语言,所以需要手动初始化父类信息,magic指明这个子类跟父类是同一类 12 obj->u.s.magic = klass->magic; 13 obj->klass = klass; 14 virAtomicIntSet(&obj->u.s.refs, 1); 15 16 PROBE(OBJECT_NEW, "obj=%p classname=%s", obj, obj->klass->name); 17 18 return obj; 19 } 20 // 如此,可以看一个子类的声明和分配例子: 21 virStreamPtr virGetStream(virConnectPtr conn) 22 { 23 virStreamPtr ret = NULL; 24 25 if (virDataTypesInitialize() < 0) 26 return NULL; 27 28 if (!(ret = virObjectNew(virStreamClass))) 29 return NULL; 30 31 ret->conn = virObjectRef(conn); 32 return ret; 33 } 34 35 struct _virStream { 36 virObject object; 37 virConnectPtr conn; 38 unsigned int flags; 39 40 virStreamDriverPtr driver; 41 void *privateData; 42 }; 43 typedef struct _virStream virStream; 44 typedef virStream *virStreamPtr; 45 46 //当调用 virObjectNew(virStreamClass)的时候,virStreamClass的objectsize在CLASS_NEW的时候已经设置为sizeof(virStream) 47 //所以最后得到一个正确的(* virStreamPtr)对象实例。