Gobject C语言库 I 对象与它的类定义

2021-10-31  本文已影响0人  Charles_linzc

Gobject 时一个为C语言提供面向对象编程的基础库。 作为一门基础语言,C语言在操作系统层面有着绝对统治的应用,但是它是一门过程语言,在面对业务处理上,由于缺乏足够的抽象,编写起来非常费力。为了减少这些缺陷,C语言生态圈也出现了不同的基础库,帮助想使用面向对象进行C语言开发的工程师进行开发,Gobject就是其中之一。
在面向对象的语言里,每一个事物或者业务会被抽象为一种类型,每一个具体的事物都是这个类的实例。在声明和创建一个方法通常用下面的格式:
VcamSource source=new VcamSouce(......);
在Gobject中,通常会这样写:
VcamSource *source;
source=g_object_new(VCAM_TYPE_SOURCE, NULL);
VCAM_TYPE_SOURCE 是一个宏定义,用来返回系统中注册的VcamSource类型。

在面向对象的语言里因为有复杂的对象与类继承管理,所以通常只需要声明VcamSource 类就可以了:
Class VcamSource{
public:
....
private:
.....

}
在C语言中是缺乏这些的,所以Gobject提供类自己的继承链和类型注册系统,在Gobject中,我们通常需要声明一个抽象类型和它的类型描述类:

#ifndef VCAM_SOURCE_H
#define VCAM_SOURCE_H

#include <glib-object.h>

#define VCAM_TYPE_SOURCE (vcam_source_get_type ())
//抽象类型
typedef struct _VcamSoure VcamSource;   
struct  _VcamSoure {
    GObject parent_instance;
};

//抽象类型的类
typedef struct _VcamSoureClass VcamSourceClass;
struct _VcamSoureClass {
    GObjectClass parent_class;
};

GType vcam_source_get_type(void);

#endif

可以看出VcamSource抽象类型其实就是一个struct 结构体, 它包含至少一个属性GObject parent_instance;, 这表示的是一个继承关系: VcamSource继承自 GObject (这个属性必须为第一个元素)。
_VcamSoureClass 是VcamSource的类型,它用来描述VcamSource和包含这一个类事务的通用属性或方法。它的第一个属性是GObjectClass,也表示的是继承关系,且 GObjectClass正是GObject的类。
在这个定义中,宏定义VCAM_TYPE_SOURCE对应的是一个返回GType 类型的方法,他正对应Gobject创建实例的第一个参数:
source=g_object_new(VCAM_TYPE_SOURCE, NULL);
VCAM_TYPE_SOURCE实际上是vcam_source_get_type()方法的调用; 这个方法主要做两件事情:声明一个VcamSource的Gtype类型;把这个类型发注册到Gobject的类型系统里,这样才可以通过g_object_new来初始化。它的具体实现是在VcamSource.c文件里;vcam_source_get_type的实现内容大概如下:

GType vcam_source_get_type(void)
{
  static GType source_type = 0;

  if (!media_type)
  {
   //声明一个GTypeInfo类型
     static const GTypeInfo source_info = {
        sizeof(VcamSourceClass),                    /* class structure size */
        NULL,                                                    /* base class initializer */
        NULL,                                                   /* base class finalizer */
        (GClassInitFunc)VcamSource_class_init,  /* class initializer */
        NULL,                                                  /* class finalizer */
        NULL,                                               /* class data */
        sizeof(VcamSource),                       /* instance structure size */
        16,                                                  /* preallocated instances */
        NULL,                                             /* instance initializer */
        NULL                                             /* function table */
     };
    //将GTypeInfo info注册到Gobject的type系统里
     media_type = g_type_register_static(
            G_TYPE_OBJECT,                 /* parent class */
            "Media",                       /* type name */
            &media_info,                   /* GTypeInfo struct (above) */
            0);                            /* flags */
  }

  return source_type ;
}

g_type_register_static(parent_id, name, type_info, options) 用于类型的注册,他的参数如下:
parent_id: 父类标识,Object类的标识就是通过G_TYPE_OBJECT宏获取
name: 类型名称
typeinfo: GTypeInfo结构,里面包含了对新类型的描述
options: 标识符,例如标准虚类等。
在看一下,source_info的声明,里面包含了很多内容,我们需要了解的包含基础类的初始化,class类型的初始化,实例的初始化等等。这些方法的声明如下:
typedef void (GBaseInitFunc) (gpointer g_class);
typedef void (
GBaseFinalizeFunc) (gpointer g_class);
typedef void (GClassInitFunc) (gpointer g_class, gpointer class_data);
typedef void (
GClassFinalizeFunc) (gpointer g_class, gpointer class_data);
typedef void (*GInstanceInitFunc) (GTypeInstance *instance, gpointer g_class);
如果要一个一个实现,确实也是很费劲的事情,GObject也考虑了这一点,所以提供了一个新的宏定义,它是声明在.c文件里:

#include "VcamSource.h"

G_DEFINE_TYPE(VcamSource, vcam_source, G_TYPE_OBJECT)   

static void
vcam_source_class_init(VcamSourceClass* class) {   //类初始化方法

}

 static void
 vcam_source_init(VcamSource* d) {   //实例初始化方法

}

 int  main(int argc, char** argv) {
     GType dtype;
     VcamSource* d;
     
          dtype = vcam_source_get_type(); /* or d = T_TYPE_DOUBLE */
        if (dtype)
             g_print("Registration was a success. The type is %lx.\n", dtype);
        else
              g_print("Registration failed.\n");
     return 0;
 }

G_DEFINE_TYPE是在.c文件里出现的,他做了以下的工作:

G_DEFINE_TYPE很显然简化了我们的大量工作,但是要注意遵循对初始化函数的命名规范。
在面向对象的语言里,通常我们需要类型映射,需要检查某个实例是否试我们想要的类型,类似于:
source2 =VcamSoure(obj);
obj instanceof VcamSoure;
在Object里,同样使用宏定义来实现前两项:
#defind VCAM_SOURCE(obj) ....
#defind VCAM_IS_SOURCE(obj) ....
这有需要在.h加入很多行,于是为了更简洁, Gobject 提供了一个新的宏 G_DECLARE_FINAL_TYPE, 它可以做下面这些事情:

#ifndef VCAM_SOURCE_H
#define VCAM_SOURCE_H

#include <glib-object.h>

#define VCAM_TYPE_SOURCE (vcam_source_get_type())
G_DECLARE_FINAL_TYPE(VcamSource, vcam_source, VCAM, SOURCE, GObject)

struct  _VcamSoure {
    GObject parent_instance;
};


struct _VcamSoureClass {
    GObjectClass parent_class;
};

#endif /* __VCAM_SOURCE_H__ */

但是宏G_DECLARE_FINAL_TYPE有个缺陷,它不允许有任何子对象,相当于用Final修饰了VcamSoure 。如果需要有子对象,就需要使用另外一个宏G_DECLARE_DERIVABLE_TYPE 。

上一篇下一篇

猜你喜欢

热点阅读