本章重点介绍了GObject子类的实现,例如创建自定义继承类,或者实现GTK +窗口类的子类。
在整个章节中,使用文件查看器程序的作为示例,其具有用于表示单个文件查看的ViewerFile类,以及具有特殊功能的不同类型的文件(例如音频文件)的各种派生类。 示例应用程序还支持通过使用ViewerEditable接口编辑文件(例如,调整正在查看的照片)。
1、头文件实现

编写GObject代码之前的第一步是编写类型的头文件,其中包含所需的类型,函数和宏定义。 这些元素中的每一个都只是GObject所有用户遵循的约定,并且在多年的开发基于GObject的代码的经验中进行了改进。 如果你正在写一个库,那么遵守这些约定是尤为重要的; 您的用户将会假定你已经遵循这些约定。 即使你不是在写库,遵守这些约定也会帮助其他想要在你的项目上工作的人。
为您的标题和源代码选择一个约定的名称,并坚持下去:
(1)使用破折号将前缀与typename分开:viewer-file.h和viewer-file.c(这是Nautilus和大多数GNOME库使用的约定)。

(2)使用下划线将前缀与typename分开:viewer_file.h和viewer_file.c。

(3)不要将前缀与typename:viewerfile.h和viewerfile.c分开。 (这是GTK +使用的惯例)

有些人喜欢前两种方法:它使阅读文件名更为容易。
任何GType的基本约定在“约定”一节中描述。
如果要在命名空间'viewer'中声明一个名为'file'的类型,请命名实例类型为ViewerFile,类类型命名为ViewerFileClass(名称区分大小写)。 约定的方法是根据类型是基类还是派生类型的不同而不同。
Final types类型不能进一步子类化,并且应该是新类型的默认选择 - 将Final types更改为可继承的类型始终是与现有代码使用兼容的更改,但相反的往往会导致问题。 Final types使用G_DECLARE_FINAL_TYPE声明,并且要求在源代码(而不是头文件)中声明的实例结构体。

/* inclusion guard */ #ifndef __VIEWER_FILE_H__ #define __VIEWER_FILE_H__ #include <glib-object.h> * Potentially, include other headers on which this header depends. G_BEGIN_DECLS * Type declaration. #define VIEWER_TYPE_FILE viewer_file_get_type () G_DECLARE_FINAL_TYPE (ViewerFile, viewer_file, VIEWER, FILE, GObject) * Method definitions. ViewerFile *viewer_file_new (void); G_END_DECLS #endif /* __VIEWER_FILE_H__ */ 继承类可以被子类化,其类和实例结构构成公共API的一部分,如果API稳定性关注,则不能更改。 它们使用G_DECLARE_DERIVABLE_TYPE声明: /* inclusion guard */ #ifndef __VIEWER_FILE_H__ #define __VIEWER_FILE_H__ #include <glib-object.h> * Potentially, include other headers on which this header depends. G_BEGIN_DECLS * Type declaration. #define VIEWER_TYPE_FILE viewer_file_get_type () G_DECLARE_DERIVABLE_TYPE (ViewerFile, viewer_file, VIEWER, FILE, GObject) struct _ViewerFileClass GObjectClass parent_class; /* Class virtual function fields. */ void (* open) (ViewerFile *file, GError **error); /* Padding to allow adding up to 12 new virtual functions without * breaking ABI. */ gpointer padding[12]; * Method definitions. ViewerFile *viewer_file_new (void); G_END_DECLS #endif /* __VIEWER_FILE_H__ */ 头文件的约定是将最少的头文件#include到需要编译该头文件的顶部。 这允许客户端代码简单地#include“viewer-file.h”,而不需要知道viewer-file.h的先决条件。
2、源代码实现

在源码里面第一步应该先#include需要的头文件

#include "viewer-file.h" /* Private structure definition. */ typedef struct { gchar *filename; /* stuff */ } ViewerFilePrivate; * forward definitions 如果这个类使用 G_DECLARE_FINAL_TYPE声明为不可继承的final types,那么他的实例结构体应当定义在.c文件中。
struct _ViewerFile
  GObject parent_instance;
  /* Other members, including private data. */
调用G_DEFINE_TYPE宏(或G_DEFINE_TYPE_WITH_PRIVATE如果您的类需要私有数据 - final types不需要私有数据),使用类型名称,函数前缀和父类GType来减少所需的代码数量。这个宏将做如下操作:
(1)实现viewer_file_get_type函数
(2)定义可以从整个.c文件访问的父类指针
(3)将私有实例数据添加到该类型(如果使用G_DEFINE_TYPE_WITH_PRIVATE)
如果使用G_DECLARE_FINAL_TYPE(参见“Boilerplate头代码”一节)将类声明为final,那么私有数据应该放在实例结构中,应该使用ViewerFile和G_DEFINE_TYPE替代G_DEFINE_TYPE_WITH_PRIVATE。final类型的实例结构不会公开暴露,也不会嵌入到任何派生类的实例结构中(因为该类是final);所以它的大小可以变化,而不会导致使用该类的代码不兼容。相反,可继承类的私有数据必须包含在私有结构中,必须使用G_DEFINE_TYPE_WITH_PRIVATE。

G_DEFINE_TYPE (ViewerFile, viewer_file, G_TYPE_OBJECT)

G_DEFINE_TYPE_WITH_PRIVATE (ViewerFile, viewer_file, G_TYPE_OBJECT)

也可以使用G_DEFINE_TYPE_WITH_CODE宏来控制get_type函数实现-例如,添加一个调用G_IMPLEMENT_INTERFACE宏来实现一个接口。
GPP是的简单GObject实现,在内部使用zeromq。 GPP不是zeromq GLib包装器。 它提供了一个GPPQueue对象,该对象将来自GPPClient的请求中继到GPPWorker,并从工作者到客户端的答复以简单字符串的形式出现。 它实现了心跳,这意味着,如果一个工作程序以某种方式失败,则客户端将能够再次发出其请求,并且具有每个请求的重试限制。 至少在最近使用的基础上挑选工人。 一个人可以无差别地实例化并在同一过程中或在单独的过程中使用所有这些对象。 它没有实现客户端优先级,这取决于用户。 mkdir build cd build meson .. ninja 您可以通过以下方式查看可用选项: mesonconf 您可以使用-D标志设置它们,例如: meson -Ddisable-introspect 本文旨在介绍GObject如何自定义类,GObject的一些基础概念(类、对象、实例)等可以自行查阅资料了解。 GObject提供了丰富的宏定义,使用G_DEFINE_TYPE 宏定义可以帮助我们快速的定义一个的类。当然如果不想借助这个宏定义,也可以自己实现XXX_get_type()函数,在该行内调用g_type_register_static() 注册的类。我们在使用g_object_n... 前面啰嗦的太多了,其实最简单的学习方式就是看代码,所以就发上来,在这个例子中定义了human接口,baby类以及其派生类boy测试用例展示了使用GObject创建对象和解阔,实现继承,以及属性和信号等的使用方法代码(后面有链接)如果运行正确会输出如下, **************************************init the type system************... 在底层代码和库的头文件中经常看到 __BEGIN_DECLS 和 __END_DECLS这两个宏,一直不太理解,今天特意查了一下,才知道它有这么大的用处。 首先看一下他们的宏定义: sys/cdefs.h #if defined(__cplusplus) #define __BEGIN_DECLS extern "C" { #define __END_DECLS ... Gobject 系统提供了一个灵活的、可扩展的、并且容易映射到其他语言的面向对象的 C 语言框架. (1)是Glib库的动态类型系统实现,它实现了:   [1] 基于引用计数的内存管理   [2] 实例的构造和析构   [3] 通用的set/get的属性获取方法   [4] 简单易用的信号机制 GObject 的动态类型系统允许程序在运行时进行类型注册,主要目的有两个: (1)使用面向对象的设计方法来编程,GObject 仅依赖于 GLib 和 li 一、接口定义 GObject接口如何工作的理论在“非实例化类类型:接口”一节中给出。 本节介绍如何定义实现一个接口。 第一步是取一个正确的名称。 该接口定义了两种方法: #ifndef __VIEWER_EDITABLE_H__ #define __VIEWER_EDITABLE_H... 最近在阅读 GStreamer 源代码,有些不太懂的地方,来学习GObject的简单使用,够用就行了 GObject 告诉我们,使用 C 语言编写程序时,可以运用面向对象这种编程思想。 一个简单的例子,用C来实现面向对象 phone.h #ifndef PHONE_H #define PHONE_H #include <glib-object.h> //TODO : #define PHONE_TYPE (phone_get_type()) //将一个 GObjec Gobject是单根继承的对象系统,但是通过interface也可以实现多继承。interface类似于C++中的抽象类,不能实例化但可以用来继承,类似U盘和移动硬盘,虽然本质上有所区别,但是它们的接口都是USB接口。并且只要它们插到计算机上,主机不关心那个东西是U盘还是移动硬盘,它只需要知道对方是个USB设备就可以了。这样,我们不需要在计算机主机中单独为U盘创造一种U盘接口,也不需要单独为移动硬 这篇文档可用于两个目的:一是作为一篇学习Glib的GObject类型系统的教程,二是用作一篇按步骤的使用GObject类型系统的入门文章。文章从如何用C语言来设计一个面向对象的类型系统开 今天开始正式研究gedit的源码,第一次看c/c++的源码,有点吃力啊,坚持不懈,慢慢来。在gedit.c文件中遇到了G_BEGIN_DECLS和G_END_DECLS,平常搞C语言的东西,我个人几乎没这样用过(怕是太菜了。。)遂顺藤摸瓜,抽丝剥茧。(以下用G宏代替)由宏定义联想这两个东西,例如#define PRINT printf("Hello World\n");在程序中可以直接使用PRIN...