在GObject中使用接口
在GObject中,接口类型(Interface)是一种可以类化(classed)但不可以实例化(instantiable)的类型。所有接口类型都是G_TYPE_INTERFACE的子类,并且不能再被继承,但可以拥有一个乃至多个先决条件。事实上,接口类型都只有类结构类型,而没有实例结构类型。
例如,GTK_TYPE_EDITABLE就是一个典型的接口类型:
typedef struct _GtkEditable GtkEditable; /* Dummy typedef */ typedef struct _GtkEditableClass GtkEditableClass; struct _GtkEditableClass { GTypeInterface base_iface; /* signals */ void (* insert_text) (GtkEditable *editable, const gchar *text, gint length, gint *position); void (* delete_text) (GtkEditable *editable, gint start_pos, gint end_pos); void (* changed) (GtkEditable *editable); /* vtable */ void (* do_insert_text) (GtkEditable *editable, const gchar *text, gint length, gint *position); void (* do_delete_text) (GtkEditable *editable, gint start_pos, gint end_pos); gchar* (* get_chars) (GtkEditable *editable, gint start_pos, gint end_pos); void (* set_selection_bounds) (GtkEditable *editable, gint start_pos, gint end_pos); gboolean (* get_selection_bounds) (GtkEditable *editable, gint *start_pos, gint *end_pos); void (* set_position) (GtkEditable *editable, gint position); gint (* get_position) (GtkEditable *editable); };
从表面上来看,GTK_TYPE_EDITABLE类拥有一个实例结构类型GtkEditable。然而,正如注释所说,这一行代码是所谓的"Dummy typedef",GtkEditable类型其实并不存在(不过我们依然可以定义指向GtkEditable类型的指针变量,也可以将其它的指针类型转化成指向GtkEditable类型的指针类型)。
为方便叙述,我们假设我们需要定义一个接口类型TYPE_HUMAN,该接口的先决条件是实现了接口TYPE_ANIMAL,而对象TYPE_BOY实现了该接口。
完整的代码如下:
#include <glib-object.h> #define TYPE_ANIMAL (animal_get_type()) #define ANIMAL(obj) (G_TYPE_CHECK_INSTANCE_CAST(obj,TYPE_ANIMAL,Animal)) #define ANIMAL_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE(obj,TYPE_ANIMAL,AnimalInterface)) typedef struct _Animal Animal; typedef struct _AnimalInterface AnimalInterface; struct _AnimalInterface { GTypeInterface base_iface; void (*sleep)(Animal *animal); void (*eat)(Animal *animal); void (*run)(Animal *animal); }; void animal_sleep(Animal *animal); void animal_eat(Animal *animal); void animal_run(Animal *animal); static void animal_default_init(AnimalInterface *iface); G_DEFINE_INTERFACE(Animal,animal,G_TYPE_INVALID); static void animal_default_init(AnimalInterface *iface) { } void animal_sleep(Animal *animal) { ANIMAL_GET_INTERFACE(animal)->sleep(animal); } void animal_eat(Animal *animal) { ANIMAL_GET_INTERFACE(animal)->eat(animal); } void animal_run(Animal *animal) { ANIMAL_GET_INTERFACE(animal)->run(animal); } /**********我是分割线**********/ #define TYPE_HUMAN (human_get_type()) #define HUMAN(obj) (G_TYPE_CHECK_INSTANCE_CAST(obj,TYPE_HUMAN,Human)) #define HUMAN_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE(obj,TYPE_HUMAN,HumanInterface)) typedef struct _Human Human; typedef struct _HumanInterface HumanInterface; struct _HumanInterface { GTypeInterface base_iface; void (*say)(Human *human); void (*study)(Human *human); }; void human_say(Human *human); void human_study(Human *human); static void human_default_init(HumanInterface *iface); G_DEFINE_INTERFACE(Human,human,TYPE_ANIMAL); static void human_default_init(HumanInterface *iface) { static gboolean is_initialized=FALSE; if (!is_initialized) { g_object_interface_install_property(iface,g_param_spec_uint("age","Age","The age of the person", 0,150,0,G_PARAM_READABLE|G_PARAM_WRITABLE)); is_initialized=TRUE; } } void human_say(Human *human) { HUMAN_GET_INTERFACE(human)->say(human); } void human_study(Human *human) { HUMAN_GET_INTERFACE(human)->study(human); } /**********我是分割线**********/ #define TYPE_BOY (boy_get_type()) #define BOY(obj) (G_TYPE_CHECK_INSTANCE_CAST(obj,TYPE_BOY,Boy)) typedef struct _Boy Boy; typedef struct _BoyClass BoyClass; struct _Boy { GObject parent; GString *name; guint age; }; struct _BoyClass { GObjectClass parent_class; }; GObject *boy_new_with_name_and_age(gchar *name,guint age); enum { PROP_0, PROP_AGE }; static void boy_init(Boy *self); static void boy_class_init(BoyClass *klass); static void boy_animal_init(AnimalInterface *iface); static void boy_human_init(HumanInterface *iface); static void boy_finalize(GObject *object); static void boy_get_property(GObject *object,guint property_id,GValue *value,GParamSpec *pspec); static void boy_set_property(GObject *object,guint property_id,const GValue *value,GParamSpec *pspec); static void boy_sleep(Animal *animal); static void boy_eat(Animal *animal); static void boy_run(Animal *animal); static void boy_say(Human *human); static void boy_study(Human *human); G_DEFINE_TYPE_EXTENDED(Boy,boy,G_TYPE_OBJECT,0,G_IMPLEMENT_INTERFACE(TYPE_ANIMAL,boy_animal_init)\ G_IMPLEMENT_INTERFACE(TYPE_HUMAN,boy_human_init)); static void boy_init(Boy *self) { self->name=NULL; } static void boy_class_init(BoyClass *klass) { GObjectClass *oclass; oclass=G_OBJECT_CLASS(klass); oclass->finalize=boy_finalize; oclass->set_property=boy_set_property; oclass->get_property=boy_get_property; g_object_class_override_property(oclass,PROP_AGE,"age"); } static void boy_animal_init(AnimalInterface *iface) { iface->sleep=boy_sleep; iface->eat=boy_eat; iface->run=boy_run; } static void boy_human_init(HumanInterface *iface) { iface->say=boy_say; iface->study=boy_study; } static void boy_finalize(GObject *object) { Boy *boy=BOY(object); g_string_free(boy->name,TRUE); G_OBJECT_CLASS(g_type_class_peek_parent(object))->finalize; } static void boy_get_property(GObject *object,guint property_id,GValue *value,GParamSpec *pspec) { Boy *boy=BOY(object); switch (property_id) { case PROP_AGE: g_value_set_uint(value,boy->age); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object,property_id,pspec); } } static void boy_set_property(GObject *object,guint property_id,const GValue *value,GParamSpec *pspec) { Boy *boy=BOY(object); switch (property_id) { case PROP_AGE: boy->age=g_value_get_uint(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object,property_id,pspec); } } static void boy_sleep(Animal *animal) { g_print("I'm sleeping now!\n"); } static void boy_eat(Animal *animal) { g_print("I hate eating vegetables!\n"); } static void boy_run(Animal *animal) { g_print("I will come first!\n"); } static void boy_say(Human *human) { g_print("Hello!\n"); } static void boy_study(Human *human) { g_print("I like Mathematics!\n"); } GObject *boy_new_with_name_and_age(gchar *name,guint age) { GObject *object; object=g_object_new(TYPE_BOY,"age",age,NULL); BOY(object)->name=g_string_new(name); return object; } /**********我是分割线**********/ int main() { GObject *boy; g_type_init(); boy=boy_new_with_name_and_age("Jim",14); animal_eat(ANIMAL(boy)); human_study(HUMAN(boy)); return 0; }
从以上代码可以看出,定义一个接口类型,主要分为以下几步:
1.定义接口相应的C语言结构:
typedef struct _Human Human; typedef struct _HumanInterface HumanInterface; struct _HumanInterface { GTypeInterface base_iface; void (*say)(Human *human); void (*study)(Human *human); };
所有接口类型的C语言结构,第一个成员必须是GTypeInterface,下面跟的函数指针,则是该接口的虚方法。注意,这里的"typedef struct _Human Human"就是所谓的"Dummy typedef",它使得我们可以为虚方法的形参中那个指向实现该接口的类的某一实例结构类型变量的指针(按惯例应为第一个形参,相当于C++中的this指针)提供一个统一的指针类型。
2.接下来,我们需要为该接口类型提供一个默认初始化函数(与下面的初始化函数相区别),该函数将负责在运行时刻在GType类型系统中添加该接口类型的信号与属性信息。由于任何一个类在实现该接口时,该默认初始化函数都会被调用,所以我们需要用一个变量来确保负责添加信号与属性的函数体只被调用一次:
static void human_default_init(HumanInterface *iface) { static gboolean is_initialized=FALSE; if (!is_initialized) { g_object_interface_install_property(iface,g_param_spec_uint("age","Age","The age of the person", 0,150,0,G_PARAM_READABLE|G_PARAM_WRITABLE)); is_initialized=TRUE; } }
3.然后,我们需要一个在运行时刻负责在GType类型系统中进行注册的函数human_get_type。当然,我们可以自己“手写”(也许用词不是很准确)这个函数。不过为方便起见我们可以使用宏G_DEFINE_INTERFACE,该宏定义如下:
#define G_DEFINE_INTERFACE(TN, t_n, T_P) G_DEFINE_INTERFACE_WITH_CODE(TN, t_n, T_P, ;)
从中可以看出,该宏有三个参数TN,t_n,T_P。TN和t_n都是接口类型的名字,不同的是,TN要求组成该名字的各个单词的首字母大写,其余字母小写,而t_n则要求组成该名字的各个单词的字母都要小写,各个单词之间要下划线"_"分隔开。该宏要求你定义的接口类型的名字为TN##Interface,接口类型的初始化函数为t_n##_default_init("##"是C语言预处理操作符)。T_P则是该接口类型的先决条件(即实现TN##Interface接口的类在实现该接口之前要实现的接口)GType ID。如果你定义的接口的先决条件不止一个,你可以使用G_DEFINE_INTERFACE_WITH_CODE宏以及g_type_interface_add_prerequisite函数。
4.为方便使用,我们需要提供一些宏以及所谓的helper function:
#define TYPE_HUMAN (human_get_type()) #define HUMAN(obj) (G_TYPE_CHECK_INSTANCE_CAST(obj,TYPE_HUMAN,Human)) #define HUMAN_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE(obj,TYPE_HUMAN,HumanInterface)) void human_say(Human *human) { HUMAN_GET_INTERFACE(human)->say(human); } void human_study(Human *human) { HUMAN_GET_INTERFACE(human)->study(human); }
宏HUMAN会检测指针obj指向的实例结构类型变量所属的类是否实现了TYPE_HUMAN接口,如果没有,会发出警告,并返回NULL,如果有,则会返回一个指向Human类型的新指针(虽然Human类型实际上并不存在)。
5.接下来,我们需要让一个类实现该接口,也即提供接口中虚方法的实现并提供一个初始化函数对接口结构变量中的函数指针进行赋值:
static void boy_say(Human *human); static void boy_study(Human *human); static void boy_human_init(HumanInterface *iface) { iface->say=boy_say; iface->study=boy_study; } static void boy_say(Human *human) { g_print("Hello!\n"); } static void boy_study(Human *human) { g_print("I like Mathematics!\n"); }
当然,我们还需要在TYPE_BOY类注册时说明该类实现了TYPE_HUMAN接口,为此,我们在这里使用G_IMPLEMENT_INTERFACE宏,该宏需要配合宏G_DEFINE_TYPE_EXTENDED使用:
G_DEFINE_TYPE_EXTENDED(Boy,boy,G_TYPE_OBJECT,0,G_IMPLEMENT_INTERFACE(TYPE_ANIMAL,boy_animal_init)\ G_IMPLEMENT_INTERFACE(TYPE_HUMAN,boy_human_init));
宏G_IMPLEMENT_INTERFACE的定义如下:
#define G_IMPLEMENT_INTERFACE(TYPE_IFACE, iface_init) { \ const GInterfaceInfo g_implement_interface_info = { \ (GInterfaceInitFunc) iface_init, NULL, NULL \ }; \ g_type_add_interface_static (g_define_type_id, TYPE_IFACE, &g_implement_interface_info); \ }
该宏有两个参数TYPE_IFACE和iface_init。TYPE_IFACE是被实现的接口类型的GType ID,而iface_init则是该类针对该接口的初始化函数。
2022年8月09日 00:08
Tenda is a popular brand that supplies various wireless routers that are well known for easy configuration of the WiFi network, and once a new router has been bought, one should make it ready to get it configured such that their LAN connection does move to WiFi to be used by multiple devices. tenda login Tenda is the most preferred brand in customer premises wireless equipment due to its good range and stable connection, and their routers are found in 150Mbps and 300Mbps form which can be bought based on customer visibility.
2022年9月03日 03:44
Chittagong is also another best education board under all education board Bangladesh, and this is also one of the divisions under eight education boards of the country, the Secondary and Higher Secondary Education Board has successfully completed those Junior School Certificate and Junior Dakil (Grade-8) annual final examination tests between 2nd to 11th November 2022 with the same schedule of all education board. Junior Certificate Result chittagong Board The School Education Department has announced there are lakhs of students are appeared and participated in the JSC & JDC terminal examinations 2022 from all districts of Chittagong division, the Grade 8th standard examinations are successfully completed and the students are waiting to get JSC Result 2022 with total marksheet with subject wise marks.
2023年12月09日 03:39
A very Wonderful blog. We believe that you have a busy, active lifestyle and also understand you need marijuana products from time to time. We’re ICO sponsored and in collaboration with doctors, deliveries, storefronts and deals worldwide, we offer a delivery service – rated
2024年1月08日 18:48
Every one of the substance you said in post is too great and can be extremely helpful. I will remember it, much obliged for sharing the data continue upgrading, looking forward for more posts.Thanks . Decent to be going to your web journal once more, it has been months for me. Well this article i’ve been sat tight for so long. I require this article to finish my task in the school, and it has same theme with your article. Much obliged, awesome offer. This is such an extraordinary asset, to the point that you are giving and you give it away for nothing. I cherish seeing sites that comprehend the benefit of giving a quality asset to free. It is the old what circumvents comes around schedule
2024年1月08日 19:01
That appears to be excellent however i am still not too sure that I like it. At any rate will look far more into it and decide personally
2024年1月08日 19:06
Such a very useful article. Very interesting to read this article.I would like to thank you for the efforts you had made for writing this awesome article.
2024年1月08日 19:26
I’ve read some good stuff here. Definitely worth bookmarking for revisiting. I surprise how much effort you put to create such a great informative website.
2024年1月08日 19:28
Thank you so much as you have been willing to share information with us. We will forever admire all you have done here because you have made my work as easy as ABC.
2024年1月08日 19:41
That is the excellent mindset, nonetheless is just not help to make every sence whatsoever preaching about that mather. Virtually any method many thanks in addition to i had endeavor to promote your own article in to delicius nevertheless it is apparently a dilemma using your information sites can you please recheck the idea. thanks once more
2024年1月08日 19:48
On that website page, you'll see your description, why not read through this
2024年1月08日 19:50
Thank you so much as you have been willing to share information as ABC.
2024年1月08日 20:16
The PCSO Lotto Result today and yesterday this October 2023 is here! Refresh page for official winning numbers - 6/58, 6/55, 6/49, 6/45, 6/42, Swertres
2024年1月08日 20:28
I’ve read some good stuff here. Definitely worth bookmarking for revisiting. I surprise how much effort you put to create such a great informative website.
2024年1月08日 20:32
On that website page, you'll see your description, why not read through this
2024年1月08日 20:40
This may be the correct weblog for everyone who is hopes to discover this topic.
2024年1月08日 20:41
Thanks for every other informative site. The place else may just I get that kind of information written in such an ideal means? I have a venture that I’m just now operating on, and I have been on the look out for such information
2024年1月08日 20:56
On that website page, you'll see your description, why not read through this
2024年1月08日 20:56
I definitely enjoying every little bit of it and I have you bookmarked to check out new stuff you post
2024年1月08日 21:00
I've found this interesting! Check it out!
2024年1月08日 21:14
I think that thanks for the valuabe information and insights you have so provided here.
2024年1月08日 21:22
I definitely enjoying every little bit of it and I have you bookmarked to check out new stuff you post
2024年1月08日 21:23
Thanks for every other informative site. The place else may just I get that kind of information written in such an ideal means? I have a venture that I’m just now operating on, and I have been on the look out for such information
2024年1月08日 21:38
I wanted to thank you for this great read!! I definitely enjoying every little bit of it I have you bookmarked to check out new stuff you post
2024年1月08日 21:46
Thank you for helping people get the information they need. Great stuff as usual. Keep up the great work!!
2024年1月08日 21:52
Really a great addition. I have read this marvelous post. Thanks for sharing information about it. I really like that
2024年1月08日 22:08
This is a great inspiring article.I am pretty much pleased with your good work.You put really very helpful information
2024年1月08日 22:22
I wanted to thank you for this great read!! I definitely enjoying every little bit of it I have you bookmarked to check out new stuff you post
2024年1月08日 22:24
It's always exciting to read articles from other writers and practice something from their web sites
2024年1月08日 22:57
Admiring the time and effort you put into your blog and detailed information you offer!.
2024年1月08日 23:39
I feel very grateful that I read this. It is very helpful and very informative and I really learned a lot from it.
2024年1月08日 23:52
I truly welcome this superb post that you have accommodated us. I guarantee this would be valuable for the vast majority of the general population. I am reading your writing well. I know a site that might be helpful for your writing. please read my article and tell us your impressions. After reading your article I was amazed. I know that you explain it very well. And I hope that other readers will also experience how I feel after reading your article . This is an excellent post I seen thanks to share it. It is really what I wanted to see hope in future you will continue for sharing such a excellent post . Really i appreciate the effort you made to share the knowledge. The topic here i found was really effective to the topic which i was researching
2024年1月09日 00:02
I am very happy to discover your post as it will become on top in my collection of favorite blogs to visit
2024年1月09日 00:06
Nice information, valuable and excellent design, as share good stuff with good ideas and concepts, lots of great information and inspiration, both of which I need, thanks to offer such a helpful information here . I’m going to read this. I’ll be sure to come back. thanks for sharing. and also This article gives the light in which we can observe the reality. this is very nice one and gives indepth information. thanks for this nice article. I was surfing the Internet for information and came across your blog. I am impressed by the information you have on this blog. It shows how well you understand this subject.
2024年1月09日 00:17
Every one of the substance you said in post is too great and can be extremely helpful. I will remember it, much obliged for sharing the data continue upgrading, looking forward for more posts.Thanks . Decent to be going to your web journal once more, it has been months for me. Well this article i’ve been sat tight for so long. I require this article to finish my task in the school, and it has same theme with your article. Much obliged, awesome offer. This is such an extraordinary asset, to the point that you are giving and you give it away for nothing. I cherish seeing sites that comprehend the benefit of giving a quality asset to free. It is the old what circumvents comes around schedule
2024年1月09日 00:28
That appears to be excellent however i am still not too sure that I like it. At any rate will look far more into it and decide personally
2024年1月09日 00:42
Thank you so much as you have been willing to share information with us. We will forever admire all you have done here because you have made my work as easy as ABC.
2024年1月09日 00:59
That is the excellent mindset, nonetheless is just not help to make every sence whatsoever preaching about that mather. Virtually any method many thanks in addition to i had endeavor to promote your own article in to delicius nevertheless it is apparently a dilemma using your information sites can you please recheck the idea. thanks once more
2024年1月09日 01:05
Thank you so much as you have been willing to share information as ABC.
2024年1月20日 19:45
I have read your excellent post. This is a great job. I have enjoyed reading your post first time. I want to say thanks for this post. Thank you...
2024年1月20日 22:04
You had a marvelous handle on the theme, nonetheless you fail to consolidate your perusers. Perhaps you ought to consider this from more than one edge.
2024年1月20日 22:20
definitely enjoying every little bit of it. It is a great website and nice share. I want to thank you. Good job! You guys do a great blog, and have some great contents. Keep up the good work
2024年1月20日 22:55
I really like the new design. It is a lot easier to use and visually attractive.
2024年1月20日 23:45
Good post. Thanks for sharing with us. I just loved your way of presentation. I enjoyed reading this .Thanks for sharing and keep writing
2024年1月21日 00:01
Thanks so much for the blog post.Really thank you! Much obliged
2024年1月21日 00:35
I found your this post while searching for some related information on blog search…Its a good post..keep posting and update the information
2024年1月21日 01:30
Thank you for taking the time to publish this information very useful!
2024年1月21日 01:48
Thank you Superb article. When I saw Jon’s email, I know the post will be good and I am surprised that you wrote it man!
2024年1月21日 02:24
This Post is providing valuable and unique information, I know that you take the time and effort to make an awesome article.
2024年1月21日 19:12
I like your post and all you share with us is up to date and quite informative, I would like to bookmark the page so I can come here again to read you, as you have done a wonderful job.
2024年1月21日 19:41
I read that Post and got it fine and informative.
2024年1月21日 20:16
I really like the new design. It is a lot easier to use and visually attractive.
2024年1月21日 20:53
Very good post.Really looking forward to read more. Really Great.
2024年1月23日 21:43
I must say this video is a very creative and wonderful explanation. Thank you for taking the time to share it.
2024年1月23日 23:18
Your blog has chock-a-block of useful information. I liked your blog's content as well as its look. In my opinion, this is a perfect blog in all aspects.
2024年1月24日 00:56
I appreciate several from the Information which has been composed, and especially the remarks posted I will visit once more
2024年1月25日 19:51
바카라 바카라사이트 우리카지노 카지노는 바카라, 블랙잭, 룰렛 및 슬롯 등 다양한 게임을 즐기실 수 있는 공간입니다. 게임에서 승리하면 큰 환호와 함께 많은 당첨금을 받을 수 있고, 패배하면 아쉬움과 실망을 느끼게 됩니다.
2024年1月25日 19:55
하노이 꼭 가봐야 할 베스트 업소 추천 안내 및 예약, 하노이 밤문화 에 대해서 정리해 드립니다. 하노이 가라오케, 하노이 마사지, 하노이 풍선바, 하노이 밤문화를 제대로 즐기시기 바랍니다. 하노이 밤문화 베스트 업소 요약 베스트 업소 추천 및 정리.
2024年1月28日 17:51
No.1 먹튀검증 사이트, 먹튀사이트, 검증사이트, 토토사이트, 안전사이트, 메이저사이트, 안전놀이터 정보를 제공하고 있습니다. 먹튀해방으로 여러분들의 자산을 지켜 드리겠습니다. 먹튀검증 전문 커뮤니티 먹튀클린만 믿으세요!!
2024年1月28日 19:13
베트남 남성전용 커뮤니티❣️ 베트남 하이에나 에서 베트남 밤문화를 추천하여 드립니다. 베트남 가라오케, 베트남 VIP마사지, 베트남 이발관, 베트남 황제투어 남자라면 꼭 한번은 경험 해 봐야할 화끈한 밤문화로 모시겠습니다.
2024年3月29日 16:28
Your blogs are easily accessible and quite enlightening so keep doing the amazing work guys.
2024年4月23日 19:27
블록체인개발 코인지갑개발 IT컨설팅 메스브레인팀이 항상 당신을 도울 준비가 되어 있습니다. 우리는 마음으로 가치를 창조한다는 철학을 바탕으로 일하며, 들인 노력과 시간에 부흥하는 가치만을 받습니다. 고객이 만족하지 않으면 기꺼이 환불해 드립니다.
https://xn--539awa204jj6kpxc0yl.kr/
2024年6月02日 21:25
The tech-original mission is to help you better understand technology, and make better decisions in the fields of IT, Tech, and Crypto.
https://www.tech-original.com/
2024年6月07日 16:40
The tech-original mission is to help you better understand technology, and make better decisions in the fields of IT, Tech, and Crypto.
https://www.tech-original.com/