接口及.h文件
在面向?qū)ο笳Z言里者春,接口是一個(gè)重要的概念破衔。接口聲明了一套函數(shù)(對(duì)應(yīng)相應(yīng)的行為要求),但是并不實(shí)現(xiàn)它們钱烟,而是讓繼承這個(gè)接口的類型來實(shí)現(xiàn)它晰筛。這樣繼承這個(gè)接口的類型就將具有相似的行為表現(xiàn)(輸入相同類型的參數(shù),返回相同類型的結(jié)果)拴袭。
Interface iMediaType{
Format getFormat();
}
在gobject中读第,同樣也實(shí)現(xiàn)了接口的機(jī)制,它的定義稍顯復(fù)雜一些拥刻, 它的頭文件如下:
#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, 有了這個(gè)宏,可以:
a. 省略typedef struct _VcamIMediaType VcamIMediaType 和 typedef struct _VcamIMediaTypeInterface VcamIMediaTypeInterface的定義般哼。
b. 省略 gtype vcam_imediatype_get_type (void)的定義吴汪。
c. 自動(dòng)增加其它一些宏定義: VCAM_IMEDIATYPE(object), VCAM_IS_DEDIATYPE(obj) ...省略了類型的定義, 可以看到?jīng)]有 struct _VcamIMediaType, 因?yàn)樽鳛榻涌谑遣粦?yīng)該有實(shí)現(xiàn)的蒸眠。
用_VcamIMediaTypeInterface 替代 _VcamIMediaTypeClass漾橙, 并且第一個(gè)元素必須為GTypeInterface
從頭文件來說, 接口的定義還是非常類似于普通對(duì)象的定義楞卡,所以雖繁麻煩了寫霜运,但還算容易寫。 接口的一個(gè)作用就是定義一套標(biāo)準(zhǔn)行為(方法)蒋腮, 這個(gè)工作需要在 _VcamIMediaTypeInterface來完成淘捡,在.h文件中需要在類型的接口中聲明所有的方法,這里我們聲明了一個(gè)方法void (get) (VcamIMediaType self, Format * formatprt);徽惋, 同時(shí)提供了一個(gè)滿足Gobject風(fēng)格的幫助方法的定義void vcam_imediatype_get(VcamIMediaType self, Format formatprt)**案淋。
接口的.c文件
在面向?qū)ο笳Z言中,一般定義了接口的形式(如.h文件內(nèi)容)险绘,就不需要在做額外的工作踢京。但是在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文件與普通對(duì)象的.c文件也是很相似的:
G_DEFINE_INTERFACE 替代了 G_DEFINE_TYPE
由于沒有類型的結(jié)構(gòu)體宦棺,所以也省略了類型的初始化函數(shù)瓣距。
仍舊需要定義 類的初始化函數(shù), G_DEFINE_INTERFACE有它的聲明代咸, 在類的初始化函數(shù)里可以添加屬性和信號(hào)蹈丸,如果沒有需要,可以省略為空。
提供幫助函數(shù)的實(shí)現(xiàn) vcam_imediatype_get逻杖。
繼承接口
一個(gè)具體的類型繼承接口奋岁,就是要實(shí)現(xiàn)接口聲明的所有函數(shù),從而具有接口表述的行為特征:
#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) {
//注冊(cè)私有屬性
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
}
如上面的代碼荸百,繼承一個(gè)接口可以按下面的順序來做:
- 正常的創(chuàng)建和聲明一個(gè)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è)參數(shù)G_IMPLEMENT_INTERFACE宏參數(shù),這個(gè)紅參數(shù)正式用來聲明接口的女嘲,第一個(gè)參數(shù)為接口類型畜份,第二個(gè)參數(shù)為接口的綁定函數(shù)。所以我們需要在增加一個(gè)綁定函數(shù) vcam_media_interface_init:
tatic void
vcam_media_interface_init(VcamIMediaTypeInterface * iface){
iface->get = vediomedia_get; //將接口定義的方法綁定到具體子類的實(shí)現(xiàn)方法上欣尼。
}
有了這個(gè)綁定后爆雹,當(dāng)調(diào)用接口的幫助方式vcam_imediatype_get時(shí),具體子類的方法將被會(huì)調(diào)用愕鼓。最后顶别,按照接口定義,實(shí)現(xiàn)綁定函數(shù):
void vediomedia_get(VcamIMediaType* self, Format* formatprt) {
//implement here
}
到這里拒啰,一個(gè)接口從聲明到定義,最后到實(shí)現(xiàn)就完成了完慧。