美文网首页
Gobject C语言库 I 对象与它的类定义

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

作者: Charles_linzc | 来源:发表于2021-10-31 17:03 被阅读0次

    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文件里出现的,他做了以下的工作:

    • 声明了一个新类型的类的初始化函数,格式为<name space>_<name>_class_init 我们通常需要这个方法来注册属性、挂载虚函数。
    • 声明了一个新类型的初始化函数,格式为 <name space>_<name>_init,我们通常在这个函数中初始化具体实例的信息。
    • 声明了一个静态变量,让它指向新类型的类的父类。 格式为 <name space>_<name>_parent_class,可用于访问父类中的方法。
    • 定义了获取类ing的函数,格式为<name space>_<name>_get_type (),这个正是我们注册类型需要的,所以GType vcam_source_get_type(void);这一行在头文件中就可以省略了。

    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, 它可以做下面这些事情:

    • 声明了一个<name space>_<name>_get_type ()方法,而G_DEFINE_TYPE包含了对它的定义,所以我们实际上跟本不需要写这个方法。
    • 定义了一个有用的宏<NAME SPACE>_<NAME>,用来进行对象的映射。例如 VCAM_SOURCE(object)可以把普通对象类映射成我们需要的VcamSource类。
    • 定义了一个<NAME SPACE>IS<NAME>, 用来判断是否一个实例来自于我们想要的类型。例如,VCAM_IS_SOURCE(obj), 可以判断 obj是否是VcamSource的实例。
      于是,引入这个宏后,我们的.h文件就更简洁了:
    #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 。

    相关文章

      网友评论

          本文标题:Gobject C语言库 I 对象与它的类定义

          本文链接:https://www.haomeiwen.com/subject/utqialtx.html