Gobject C語言庫 IV 接口

接口及.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 VcamIMediaTypetypedef 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)就完成了完慧。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末谋旦,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子屈尼,更是在濱河造成了極大的恐慌册着,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,657評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件脾歧,死亡現(xiàn)場離奇詭異甲捏,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)鞭执,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門司顿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人兄纺,你說我怎么就攤上這事大溜。” “怎么了估脆?”我有些...
    開封第一講書人閱讀 164,057評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵钦奋,是天一觀的道長。 經(jīng)常有香客問我,道長付材,這世上最難降的妖魔是什么朦拖? 我笑而不...
    開封第一講書人閱讀 58,509評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮厌衔,結(jié)果婚禮上璧帝,老公的妹妹穿的比我還像新娘。我一直安慰自己葵诈,他們只是感情好裸弦,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著作喘,像睡著了一般理疙。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上泞坦,一...
    開封第一講書人閱讀 51,443評(píng)論 1 302
  • 那天窖贤,我揣著相機(jī)與錄音,去河邊找鬼贰锁。 笑死赃梧,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的豌熄。 我是一名探鬼主播授嘀,決...
    沈念sama閱讀 40,251評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼锣险!你這毒婦竟也來了蹄皱?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,129評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤芯肤,失蹤者是張志新(化名)和其女友劉穎巷折,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體崖咨,經(jīng)...
    沈念sama閱讀 45,561評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡锻拘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了击蹲。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片署拟。...
    茶點(diǎn)故事閱讀 39,902評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖际邻,靈堂內(nèi)的尸體忽然破棺而出芯丧,到底是詐尸還是另有隱情,我是刑警寧澤世曾,帶...
    沈念sama閱讀 35,621評(píng)論 5 345
  • 正文 年R本政府宣布缨恒,位于F島的核電站谴咸,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏骗露。R本人自食惡果不足惜岭佳,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望萧锉。 院中可真熱鬧珊随,春花似錦、人聲如沸柿隙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽禀崖。三九已至衩辟,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間波附,已是汗流浹背艺晴。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留掸屡,地道東北人封寞。 一個(gè)月前我還...
    沈念sama閱讀 48,025評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像仅财,于是被迫代替她去往敵國和親狈究。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容