用C实现C++的多态---剖析GTK的"对象" (三)

来源:互联网 发布:唐小僧 木子软件 编辑:程序博客网 时间:2024/06/08 19:33

六. 全部代码

/***********************************************************************

object.h文件

************************************************************************/
#ifndef _H_OBJECT_H_
#define _H_OBJECT_H_

#define TOP_OBJECT_TYPE  0
#define BASE_OBJECT_TYPE  GetObjectType()
#define IS_OBJECT_TYPE(obj)  IsObjectType(obj,BASE_OBJECT_TYPE)
#define BASE_OBJECT_CLASS(obj) ((CObjectClass*)GetObjectClass(obj))

typedef void (*pInitObjectCallback)(void*);
typedef void (*pInitClassCallback)(void*);

typedef struct _CObject  CObject;
typedef struct _CObjectClass CObjectClass;
typedef struct _ClassInfo  ClassInfo;

struct _CObject
{
 CObjectClass *vclass;
 short  ref_counter;
};

struct _CObjectClass
{
 int class_type;
 void (*destory)(CObject *object);
};

struct _ClassInfo
{
 char    *name;
 int     object_size;
 int     class_size;
 void (*InitObjectCallback)(void*);
 void (*InitClassCallback)(void *);
};

#ifdef __cplusplus
extern "C" {
#endif

int
GetObjectType(void);

void*
GetObjectClass(void *);

CObject *
NewObject(void);

void
DestoryObject(CObject *object);

void
AttachObject(CObject *object);

void
ReleaseObject(CObject *object);

 

void
InitObjectLib(void);

int
RegisterClassType(ClassInfo *classinfo, int parent_type);

void*
NewClassType(int class_type);

int
IsObjectType(void *obj, int type);

int
CheckClassType(int type);

#ifdef __cplusplus
}
#endif
#endif

 


/***********************************************************************

object.c文件

************************************************************************/

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "object.h"
#include "tvstring.h"
#include "debug.h"

#define MAX_CLASS_NUM  128
#define lock()
#define unlock()

typedef struct _ClassType
{
 char*    name;
 int     class_size;
 int     object_size;
 CObjectClass*  vclass;
 void (*InitClassCallback)(void*);
 void (*InitObjectCallback)(void*);
 struct _ClassType* parent;
 struct _ClassType* next;
}ClassType;

static ClassType classes[MAX_CLASS_NUM];
static ClassType *used_classes = NULL;
static ClassType *free_classes = NULL;

 


/****************************************************************/

static void
InitObjectClass(CObjectClass *vclass)
{
 if(vclass==NULL)
  return;
 
 vclass->destory = DestoryObject;
}

static void
InitObject(CObject *object)
{
 if(object==NULL)
  return;
 
 object->ref_counter = 1;
}

int
GetObjectType(void)
{
 static int type = 0;

 if( type==0 )
 {
  static ClassInfo classinfo =
  {
   "OBJECT",
   sizeof(CObject),
   sizeof(CObjectClass),
   (pInitObjectCallback)InitObject,
   (pInitClassCallback)InitObjectClass,
  };

  type = RegisterClassType(&classinfo, TOP_OBJECT_TYPE);
 }

 return type;
}

void*
GetObjectClass(void *obj)
{
 CObject *object;

 if(obj==NULL)
  return NULL;
 
 object = (CObject *)obj;
 return (void*)object->vclass;
}


CObject *
NewObject(void)
{
 return NewClassType(BASE_OBJECT_TYPE);
}

void
DestoryObject(CObject *object)
{
 if(object==NULL)
  return;
 
 free(object);
}

void
AttachObject(CObject *object)
{
 if(object==NULL)
  return;

 object->ref_counter++;
}

void
ReleaseObject(CObject *object)
{
 if(object==NULL)
  return;

 if( --object->ref_counter==0 )
  DestoryObject(object);
}


/****************************************************************/
void
InitObjectLib(void)
{
 int i;
 memset(classes, 0, sizeof(ClassType)*MAX_CLASS_NUM);
 for( i=0;i<MAX_CLASS_NUM-1;i++ )
 {
  classes[i].next = &(classes[i+1]);
 } 
 free_classes = &(classes[0]);
}

int
RegisterClassType(ClassInfo *classinfo, int parent_type)
{
 int type = 0;
 ClassType *current, *parent;

 {
  parent = (ClassType *)parent_type;

 #ifdef __DEBUG 
  if( parent &&parent->vclass==NULL )
  {
   TRACE("RegisterClassType(): parent_type is invalid/n");
   return type;
  }
 #endif

  if( classinfo->name==NULL )
  {
   TRACE("RegisterClassType(): class name is NULL/n");
   return type;
  }

  lock();
  current = used_classes;
  while(current)
  {
   if(strcmp(current->name, classinfo->name)==0 )
   {
    TRACE("RegisterClassType(): class name is redefined/n");
    unlock();
    return type;
   }
   current = current->next;
  }

  current = free_classes;
  if(current)
  {
   free_classes = free_classes->next;
   current->name = classinfo->name;
   current->parent = parent;
   current->class_size = classinfo->class_size;
   current->InitClassCallback = classinfo->InitClassCallback;
   current->InitObjectCallback = classinfo->InitObjectCallback;
   current->vclass = malloc(current->class_size);
   if( current->vclass==NULL )
   {
    TRACE("RegisterClassType(): malloc vclass failed/n");
   }
   memset( current->vclass, 0, current->class_size);
   current->vclass->class_type = (int)current;
   if( parent )
   {
    memcpy(current->vclass, parent->vclass, parent->class_size);
   }
   if( current->InitClassCallback )
    current->InitClassCallback(current->vclass);
   current->next = used_classes;
   used_classes = current;
  }
  else
  {
   TRACE("RegisterClassType(): ERROR, no class in class pool/n");
  }

  unlock();
 
  type = (int)current;
 }

 return type;
}

static void
InitParentObject(ClassType *current, void *object)
{
 if( current )
 {
  if( current->parent )
   InitParentObject(current->parent, object);
  if( current->InitObjectCallback )
   current->InitObjectCallback(object);
 }
}

void *
NewClassType(int class_type)
{
 ClassType *pclass = NULL;
 void *object = NULL;

 if( pclass==0 )
  return NULL;

 #ifdef __DEBUG
 if( CheckClassType(class_type)==0 )
 {
  TRACE("NewObjectType(): invalid class_type/n");
  return NULL;
 }
 #endif
 
 pclass = (ClassType*)class_type;
 object = (CObject*)malloc(pclass->object_size);
 if( object )
 {
  ((CObject*)object)->vclass = pclass->vclass;
  InitParentObject(pclass, object);
 }

 return object;
}

int
IsObjectType(void *obj, int type)
{
 ClassType *pclass, *objtype;
 CObject *object;
 
 if( obj==NULL || type==0 )
  return 0;

 pclass = (ClassType*)type;
 object = (CObject*)obj;
 if( object->vclass==NULL )
  return 0;

 objtype = (ClassType*)object->vclass->class_type;
 while(objtype)
 {
  if( objtype==pclass )
   return 1;
  objtype = objtype->parent;
 }

 return 0;
}

int
CheckClassType(int type)
{
 ClassType *objtype;
 
 objtype = used_classes;
 while(objtype)
 {
  if( (int)objtype==type )
   return 1;
  objtype = objtype->next;
 }
 return 0;
}

 

 

原创粉丝点击