美文网首页
Gobject C语言库 IV 接口

Gobject C语言库 IV 接口

作者: Charles_linzc | 来源:发表于2021-11-01 22:34 被阅读0次

    接口及.h文件

    在面向对象语言里,接口是一个重要的概念。接口声明了一套函数(对应相应的行为要求),但是并不实现它们,而是让继承这个接口的类型来实现它。这样继承这个接口的类型就将具有相似的行为表现(输入相同类型的参数,返回相同类型的结果)。
    Interface iMediaType{
    Format getFormat();
    }
    在gobject中,同样也实现了接口的机制,它的定义稍显复杂一些, 它的头文件如下:

    #ifndef VCAME_IMEDIATYPE_H
    #define VCAME_IMEDIATYPE_H
    
    #include <glib-object.h>
    #define VCAME_IMEDIATYPE (vcam_imediatype_get_type ())
    G_DECLARE_INTERFACE(VcamIMediaType, vcam_imediatype, VCAM, IMEDIATYPE, GObject)
    
    
    struct _VcamIMediaTypeInterface
    {
        GTypeInterface parent_iface;
    
        void (*get) (VcamIMediaType *self, Format * formatprt);
      
    };
    
    void vcam_imediatype_get(VcamIMediaType* self,  Format* formatprt);
    
    #endif
    

    如果参考普通类型的定义,这里无非是做了一些修改:

    • G_DECLARE_INTERFACE 替代G_DECLARE_DERIVABLE_TYPE或G_DECLARE_FINAL_TYPE, 有了这个宏,可以:
      a. 省略typedef struct _VcamIMediaType VcamIMediaTypetypedef struct _VcamIMediaTypeInterface VcamIMediaTypeInterface的定义。
      b. 省略 gtype vcam_imediatype_get_type (void)的定义。
      c. 自动增加其它一些宏定义: VCAM_IMEDIATYPE(object), VCAM_IS_DEDIATYPE(obj) ...

    • 省略了类型的定义, 可以看到没有 struct _VcamIMediaType, 因为作为接口是不应该有实现的。

    • 用_VcamIMediaTypeInterface 替代 _VcamIMediaTypeClass, 并且第一个元素必须为GTypeInterface

    从头文件来说, 接口的定义还是非常类似于普通对象的定义,所以虽繁麻烦了写,但还算容易写。 接口的一个作用就是定义一套标准行为(方法), 这个工作需要在 _VcamIMediaTypeInterface来完成,在.h文件中需要在类型的接口中声明所有的方法,这里我们声明了一个方法void (get) (VcamIMediaType self, Format * formatprt);, 同时提供了一个满足Gobject风格的帮助方法的定义void vcam_imediatype_get(VcamIMediaType self, Format formatprt)**。

    接口的.c文件

    在面向对象语言中,一般定义了接口的形式(如.h文件内容),就不需要在做额外的工作。但是在Gobject,为了让接口工作我们还需要完成.c文件:

    #include "IMediaType.h"
    
    G_DEFINE_INTERFACE(VcamIMediaType, vcam_imediatype, G_TYPE_OBJECT)
    
    static void
    vcam_imediatype_default_init(VcamIMediaTypeInterface* iface)
    {
        /* add properties and signals to the interface here */
    }
    
    void vcam_imediatype_get(VcamIMediaType* self, Format* formatprt) {
    
        VcamIMediaTypeInterface* iface;
    
        g_return_if_fail(VCAM_IS_IMEDIATYPE(self));
       
        iface = VCAM_IMEDIATYPE_GET_IFACE(self);
        g_return_if_fail(iface->get != NULL);
        iface->get(self, formatprt);
    }
    

    接口的.c文件与普通对象的.c文件也是很相似的:

    • G_DEFINE_INTERFACE 替代了 G_DEFINE_TYPE

    • 由于没有类型的结构体,所以也省略了类型的初始化函数。

    • 仍旧需要定义 类的初始化函数, G_DEFINE_INTERFACE有它的声明, 在类的初始化函数里可以添加属性和信号,如果没有需要,可以省略为空。

    • 提供帮助函数的实现 vcam_imediatype_get。

    继承接口

    一个具体的类型继承接口,就是要实现接口声明的所有函数,从而具有接口表述的行为特征:

    #include "VedioMedia.h"
    #include "IMediaType.h"
    
    G_DEFINE_TYPE_WITH_CODE(VcamVedioMedia, vcam_vediomedia, G_TYPE_OBJECT,
                           G_IMPLEMENT_INTERFACE(VCAME_IMEDIATYPE,
                                    vcam_media_interface_init))
    
    #define VCAM_SOURCE_GET_PRIVATE(obj) (\
        G_TYPE_INSTANCE_GET_PRIVATE((obj), VCAM_TYPE_VEDIOMEDIA, VcamVedioMediaPriv))
    
    enum _VCAM_MEDIA_PROPERTY {
        VCAM_MEDIA_PROPERTY0,   
        VCAM_MEDIA_FORMAT
    };
    
    struct _VcamVedioMediaPriv {
        GObject  * format;
    };
    
    static void
    vcam_vediomedia_init(VcamVedioMedia* d) {
    
    
    }
    
    static void
    vcam_vediomedia_class_init(VcamVedioMediaClass * kclass) {
        //注册私有属性
        g_type_class_add_private(kclass, sizeof(VcamVedioMediaPriv));
    
        /* override base object methods */
        GObjectClass* base_class = G_OBJECT_CLASS(kclass);
        base_class->set_property = vcam_vediomedia_set_property;
        base_class->get_property = vcam_vediomedia_get_property;
        /* install properties */
        g_object_class_install_property(base_class, VCAM_MEDIA_FORMAT,
            g_param_spec_object("format", "vedio format", "desscribe the vedio format", VCAM_TYPE_VEDIOMEDIA,G_PARAM_READWRITE));
    
    }
    
    static void
    vcam_vediomedia_set_property(GObject* object, guint property_id,
        const GValue* value, GParamSpec* pspec)
    {
        VcamVedioMedia* self = VCAM_VEDIOMEDIA(object);
        VcamVedioMediaPriv * priv = VCAM_VEDIOMEDIA_GET_PRIVATE(self);
        switch (property_id) {
        case VCAM_MEDIA_FORMAT:
    
            priv->format = g_value_get_object(value);
            break;
        default:
            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
            break;
        }
    }
    
    static void
    vcam_vediomedia_get_property(GObject* object, guint property_id,
        GValue* value, GParamSpec* pspec)
    {
        VcamVedioMedia* self = VCAM_VEDIOMEDIA(object);
        VcamVedioMediaPriv* priv = VCAM_VEDIOMEDIA_GET_PRIVATE(self);
        switch (property_id) {
        case VCAM_MEDIA_FORMAT:
            g_value_set_object(value, priv->format);
            break;
        default:
            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
            break;
        }
    }
    
    static void
      vcam_media_interface_init(VcamIMediaTypeInterface * iface){
    
            iface->get = vediomedia_get;
     }
    
    
    void vediomedia_get(VcamIMediaType* self, Format* formatprt) {
    
       //implement here
    }
    

    如上面的代码,继承一个接口可以按下面的顺序来做:

    • 正常的创建和声明一个Gobject子类型,不需要修改头文件
    • 在.c文件中,使用 G_DEFINE_TYPE_WITH_CODE 替换G_DEFINE_TYPE,如下:
    G_DEFINE_TYPE_WITH_CODE(VcamVedioMedia, vcam_vediomedia, G_TYPE_OBJECT,
                           G_IMPLEMENT_INTERFACE(VCAME_IMEDIATYPE,
                                    vcam_media_interface_init))
    

    在上面的宏定义中,增加一个参数G_IMPLEMENT_INTERFACE宏参数,这个红参数正式用来声明接口的,第一个参数为接口类型,第二个参数为接口的绑定函数。所以我们需要在增加一个绑定函数 vcam_media_interface_init

    tatic void
      vcam_media_interface_init(VcamIMediaTypeInterface * iface){
            iface->get = vediomedia_get;  //将接口定义的方法绑定到具体子类的实现方法上。
     }
    

    有了这个绑定后,当调用接口的帮助方式vcam_imediatype_get时,具体子类的方法将被会调用。最后,按照接口定义,实现绑定函数:

    void vediomedia_get(VcamIMediaType* self, Format* formatprt) {
       //implement here
    }
    

    到这里,一个接口从声明到定义,最后到实现就完成了。

    相关文章

      网友评论

          本文标题:Gobject C语言库 IV 接口

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