Gobject tutorial 七

2024-06-20 05:44
文章标签 tutorial gobject

本文主要是介绍Gobject tutorial 七,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

The GObject base class

GObject是一个fundamental classed instantiatable type,它的功能如下:

  • 内存管理
  • 构建/销毁实例
  • set/get属性方法
  • 信号
/*** GObjectClass:* @g_type_class: the parent class* @constructor: the @constructor function is called by g_object_new () to *  complete the object initialization after all the construction properties are*  set. The first thing a @constructor implementation must do is chain up to the*  @constructor of the parent class. Overriding @constructor should be rarely *  needed, e.g. to handle construct properties, or to implement singletons.* @set_property: the generic setter for all properties of this type. Should be*  overridden for every type with properties. If implementations of*  @set_property don't emit property change notification explicitly, this will*  be done implicitly by the type system. However, if the notify signal is*  emitted explicitly, the type system will not emit it a second time.* @get_property: the generic getter for all properties of this type. Should be*  overridden for every type with properties.* @dispose: the @dispose function is supposed to drop all references to other *  objects, but keep the instance otherwise intact, so that client method *  invocations still work. It may be run multiple times (due to reference *  loops). Before returning, @dispose should chain up to the @dispose method *  of the parent class.* @finalize: instance finalization function, should finish the finalization of *  the instance begun in @dispose and chain up to the @finalize method of the *  parent class.* @dispatch_properties_changed: emits property change notification for a bunch*  of properties. Overriding @dispatch_properties_changed should be rarely *  needed.* @notify: the class closure for the notify signal* @constructed: the @constructed function is called by g_object_new() as the*  final step of the object creation process.  At the point of the call, all*  construction properties have been set on the object.  The purpose of this*  call is to allow for object initialisation steps that can only be performed*  after construction properties have been set.  @constructed implementors*  should chain up to the @constructed call of their parent class to allow it*  to complete its initialisation.* * The class structure for the GObject type.* * |[<!-- language="C" -->* // Example of implementing a singleton using a constructor.* static MySingleton *the_singleton = NULL;* * static GObject** my_singleton_constructor (GType                  type,*                           guint                  n_construct_params,*                           GObjectConstructParam *construct_params)* {*   GObject *object;*   *   if (!the_singleton)*     {*       object = G_OBJECT_CLASS (parent_class)->constructor (type,*                                                            n_construct_params,*                                                            construct_params);*       the_singleton = MY_SINGLETON (object);*     }*   else*     object = g_object_ref (G_OBJECT (the_singleton));* *   return object;* }* ]|*/
struct  _GObjectClass
{GTypeClass   g_type_class;/*< private >*/GSList      *construct_properties;/*< public >*//* seldom overridden */GObject*   (*constructor)     (GType                  type,guint                  n_construct_properties,GObjectConstructParam *construct_properties);/* overridable methods */void       (*set_property)		(GObject        *object,guint           property_id,const GValue   *value,GParamSpec     *pspec);void       (*get_property)		(GObject        *object,guint           property_id,GValue         *value,GParamSpec     *pspec);void       (*dispose)			(GObject        *object);void       (*finalize)		(GObject        *object);/* seldom overridden */void       (*dispatch_properties_changed) (GObject      *object,guint	   n_pspecs,GParamSpec  **pspecs);/* signals */void	     (*notify)			(GObject	*object,GParamSpec	*pspec);/* called when done constructing */void	     (*constructed)		(GObject	*object);/*< private >*/gsize		flags;gsize         n_construct_properties;gpointer pspecs;gsize n_pspecs;/* padding */gpointer	pdummy[3];
};/*** GObject:** The base object type.* * All the fields in the `GObject` structure are private to the implementation* and should never be accessed directly.** Since GLib 2.72, all #GObjects are guaranteed to be aligned to at least the* alignment of the largest basic GLib type (typically this is #guint64 or* #gdouble). If you need larger alignment for an element in a #GObject, you* should allocate it on the heap (aligned), or arrange for your #GObject to be* appropriately padded. This guarantee applies to the #GObject (or derived)* struct, the #GObjectClass (or derived) struct, and any private data allocated* by G_ADD_PRIVATE().*/
struct  _GObject
{GTypeInstance  g_type_instance;/*< private >*/guint          ref_count;  /* (atomic) */GData         *qdata;
};

Object instantiation

g_object_new()族能够实例化任何继承自GObject的GType。族中所有函数都能保证将类结构和实例结构在GLib的类型系统中正确初始化,之后会在某个时机调用类的constructor方法。

类的constructor方法的作用如下:

  • 通过g_type_create_instance()函数分配并清空内存。
  • 使用构造属性初始化对象实例。
static GObject*
g_object_constructor (GType                  type,guint                  n_construct_properties,GObjectConstructParam *construct_params)
{GObject *object;/* create object */object = (GObject*) g_type_create_instance (type);/* set construction parameters */if (n_construct_properties){GObjectNotifyQueue *nqueue = g_object_notify_queue_freeze (object, FALSE);/* set construct properties */while (n_construct_properties--){GValue *value = construct_params->value;GParamSpec *pspec = construct_params->pspec;construct_params++;object_set_property (object, pspec, value, nqueue, TRUE);}g_object_notify_queue_thaw (object, nqueue);/* the notification queue is still frozen from g_object_init(), so* we don't need to handle it here, g_object_newv() takes* care of that*/}return object;
}

GObject能够确保所有类结构和实例结构的成员(除指向父结构的成员外)的值都被设置为0。

当所有构造相关的工作都完成,构造属性都被设置完成后,最后会调用constructed方法。

继承自GObject的对象都能重写类的constructed方法。举例如下:

#define VIEWER_TYPE_FILE viewer_file_get_type ()
G_DECLARE_FINAL_TYPE (ViewerFile, viewer_file, VIEWER, FILE, GObject)struct _ViewerFile
{GObject parent_instance;/* instance members */char *filename;guint zoom_level;
};/* will create viewer_file_get_type and set viewer_file_parent_class */
G_DEFINE_TYPE (ViewerFile, viewer_file, G_TYPE_OBJECT)static void
viewer_file_constructed (GObject *obj)
{/* update the object state depending on constructor properties *//* Always chain up to the parent constructed function to complete object* initialisation. */G_OBJECT_CLASS (viewer_file_parent_class)->constructed (obj);
}static void
viewer_file_finalize (GObject *obj)
{ViewerFile *self = VIEWER_FILE (obj);g_free (self->filename);/* Always chain up to the parent finalize function to complete object* destruction. */G_OBJECT_CLASS (viewer_file_parent_class)->finalize (obj);
}static void
viewer_file_class_init (ViewerFileClass *klass)
{GObjectClass *object_class = G_OBJECT_CLASS (klass);object_class->constructed = viewer_file_constructed;object_class->finalize = viewer_file_finalize;
}static void
viewer_file_init (ViewerFile *self)
{/* initialize the object */
}

 通过g_object_new(VIEWER_TYPE_FILE,NULL)的方式,第一次实例化ViewerFile对象时,会调用view_file_base_init函数,接着调用view_file_class_init函数。这样新对象的类结构就能够被初始化完成。

当g_object_new获取到新对象的初始化完成的类结构的索引之后,如果GObject的constructor函数被重写,那么,g_object_new函数将会调用新类型的类结构中constructor(如上例中的viewer_file_cosntructed,实际上也是新类ViewFileClass中GObject的constructor,这是因为,ViewFile是一个final类型对象)来创建新对象。

gpointer
g_object_new (GType	   object_type,const gchar *first_property_name,...)
{GObject *object;
....../* short circuit for calls supplying no properties */if (!first_property_name)return g_object_new_with_properties (object_type, 0, NULL, NULL);......return object;
}GObject *
g_object_new_with_properties (GType          object_type,guint          n_properties,const char    *names[],const GValue   values[])
{GObjectClass *class, *unref_class = NULL;GObject *object;
......class = g_type_class_peek_static (object_type);if (class == NULL)class = unref_class = g_type_class_ref (object_type);if (n_properties > 0){
......}elseobject = g_object_new_internal (class, NULL, 0);
......return object;
}static gpointer
g_object_new_internal (GObjectClass          *class,GObjectConstructParam *params,guint                  n_params)
{
......GObject *object;
......if G_UNLIKELY (CLASS_HAS_CUSTOM_CONSTRUCTOR (class))return g_object_new_with_custom_constructor (class, params, n_params);object = (GObject *) g_type_create_instance (class->g_type_class.g_type);......
}static gpointer
g_object_new_with_custom_constructor (GObjectClass          *class,GObjectConstructParam *params,guint                  n_params)
{
......GObject *object;....../* construct object from construction parameters */object = class->constructor (class->g_type_class.g_type, class->n_construct_properties, cparams);......
return object
}

Chaining up to its parent

在继承Gobject的新类型的初始化过程中,如上所述,会存在GObjectClass的constructor被用户改写的情况,那么,用户为新对象设置的constructor与GObjectClass的默认constructor之间是什么关系呢?

如下图所示:

 如图,有两个类结构,GObjectClass和TstrClass,两个类都有各自的finalize函数,TstrClass的finalize函数用于销毁Tstr 实例结构中与其本身相关的数据(不包含Tstr结构中其父结构GObjectClass中的数据),TStrClass的finalize函数在最后会调用其父类GObjectClass的finalize函数来销毁GObject中的数据。这期间有个函数调用关系,这个调用关系就是图示“chain up”的含义。

我们在gtk库中找个finalize函数来具体说明一下。

static void
gtk_print_backend_cups_finalize (GObject *object)
{GtkPrintBackendCups *backend_cups;GTK_DEBUG (PRINTING, "CUPS Backend: finalizing CUPS backend module");backend_cups = GTK_PRINT_BACKEND_CUPS (object);g_free (backend_cups->default_printer);backend_cups->default_printer = NULL;gtk_cups_connection_test_free (backend_cups->cups_connection_test);backend_cups->cups_connection_test = NULL;g_hash_table_destroy (backend_cups->auth);g_free (backend_cups->username);#ifdef HAVE_COLORDg_object_unref (backend_cups->colord_client);
#endifg_clear_object (&backend_cups->avahi_cancellable);g_clear_pointer (&backend_cups->avahi_default_printer, g_free);g_clear_object (&backend_cups->dbus_connection);g_clear_object (&backend_cups->secrets_service_cancellable);if (backend_cups->secrets_service_watch_id != 0){g_bus_unwatch_name (backend_cups->secrets_service_watch_id);}g_list_free_full (backend_cups->temporary_queues_in_construction, g_free);backend_cups->temporary_queues_in_construction = NULL;g_list_free_full (backend_cups->temporary_queues_removed, g_free);backend_cups->temporary_queues_removed = NULL;backend_parent_class->finalize (object);
}

 现在我们可以回到我们之前的问题,类似于finalize,constructor也有“chain up“的关系存在。

同样的,我们在gtk库中找一个constructor函数看看。

static GObject*
gtk_button_constructor (GType                  type,guint                  n_construct_properties,GObjectConstructParam *construct_params)
{GObject *object;GtkButton *button;object = (* G_OBJECT_CLASS (gtk_button_parent_class)->constructor) (type,n_construct_properties,construct_params);button = GTK_BUTTON (object);button->constructed = TRUE;if (button->label_text != NULL)gtk_button_construct_child (button);return object;
}

回到我们之前的话题,在初始化过程中,通过"chain up"会调用到g_object_constructor,只不过constructor的调用顺序与finalize相反。因为,我们需要g_object_constructor函数调用g_type_create_instance来为我们的新类型实例分配空间。同时,instance_init函数也会在此时执行。instance_init的返回,也意味这新类型的初始化过程完成。之后,用户就能使用新类型。

GTypeInstance*
g_type_create_instance (GType type)
{TypeNode *node;GTypeInstance *instance;GTypeClass *class;gchar *allocated;gint private_size;gint ivar_size;guint i;node = lookup_type_node_I (type);......class = g_type_class_ref (type);/* We allocate the 'private' areas before the normal instance data, in* reverse order.  This allows the private area of a particular class* to always be at a constant relative address to the instance data.* If we stored the private data after the instance data this would* not be the case (since a subclass that added more instance* variables would push the private data further along).** This presents problems for valgrindability, of course, so we do a* workaround for that case.  We identify the start of the object to* valgrind as an allocated block (so that pointers to objects show up* as 'reachable' instead of 'possibly lost').  We then add an extra* pointer at the end of the object, after all instance data, back to* the start of the private area so that it is also recorded as* reachable.  We also add extra private space at the start because* valgrind doesn't seem to like us claiming to have allocated an* address that it saw allocated by malloc().*/private_size = node->data->instance.private_size;ivar_size = node->data->instance.instance_size;......allocated = g_malloc0 (private_size + ivar_size);instance = (GTypeInstance *) (allocated + private_size);for (i = node->n_supers; i > 0; i--){TypeNode *pnode;pnode = lookup_type_node_I (node->supers[i]);if (pnode->data->instance.instance_init){instance->g_class = pnode->data->instance.class;pnode->data->instance.instance_init (instance, class);}}......instance->g_class = class;if (node->data->instance.instance_init)node->data->instance.instance_init (instance, class);return instance;
}

初始化流程如下表

这篇关于Gobject tutorial 七的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1077264

相关文章

A Tutorial on Near-Field XL-MIMO Communications Towards 6G【论文阅读笔记】

此系列是本人阅读论文过程中的简单笔记,比较随意且具有严重的偏向性(偏向自己研究方向和感兴趣的),随缘分享,共同进步~ 论文主要内容: 建立XL-MIMO模型,考虑NUSW信道和非平稳性; 基于近场信道模型,分析性能(SNR scaling laws,波束聚焦、速率、DoF) XL-MIMO设计问题:信道估计、波束码本、波束训练、DAM XL-MIMO信道特性变化: UPW ➡ NU

beanstalkc Tutorial 中文版

英文原版:https://github.com/earl/beanstalkc/blob/wip-doc-rtfd/doc/tutorial.rst 背景介绍: Beanstalk,一个高性能、轻量级的分布式内存队列系统。而beanstalkc是Beanstalk的一个python客户端库。看题主写的通俗易懂,就直接翻译过来。 开始: 启动服务端beanstalkd进程来监听14711端口,可以

OpenGuass under Ubuntu_22.04 install tutorial

今天开始短学期课程:数据库课程设计。今天9点左右在SL1108开课,听陈老师讲授了本次短学期课程的要求以及任务安排,随后讲解了国产数据库的三层架构的逻辑。配置了大半天才弄好,放一张成功的图片,下面开始记录成功的步骤: My operator system is Ubuntu_22.04. procedures sudo wget https://opengauss.obs.cn-so

Tutorial : Getting Started with Kubernetes on your Windows Laptop with Minikube

https://rominirani.com/tutorial-getting-started-with-kubernetes-on-your-windows-laptop-with-minikube-3269b54a226#.d9lmuvzf2 本文的注意事项: 1, 截止到2017.01.20, window上的kubernetes依然是实验性的, 存在各种不可预知的bug

OpenCV2.4.10之samples_cpp_tutorial-code_learn-----ImgTrans(仿射变换)

本系列学习笔记参考自OpenCV2.4.10之opencv\sources\samples\cpp\tutorial_code和http://www.opencv.org.cn/opencvdoc/2.3.2/html/genindex.html 本博文将继续学习opencv-tutorial-code中的ImgTrans,这里讲主要介绍仿射变换。仿射变换是直角坐标系的一种,描述的是一

OpenCV2.4.10之samples_cpp_tutorial-code_learn-----ImgTrans(图片边框与图片卷积)

本系列学习笔记参考自OpenCV2.4.10之 opencv\sources\samples\cpp\tutorial_code和 http://www.opencv.org.cn/opencvdoc/2.3.2/html/genindex.html 本博文将继续介绍如何给一张图片添加边框以及如何对一张图片进行卷积。核心函数为copyMakeBorder与filter2D 1.co

OpenCV2.4.10之samples_cpp_tutorial-code_learn-----ImgTrans(Canny边缘检测)

本系列学习笔记参考自OpenCV2.4.10之 opencv\sources\samples\cpp\tutorial_code和 http://www.opencv.org.cn/opencvdoc/2.3.2/html/genindex.html 本博文接下来将介绍图像变换相关的Demo,如下图所示: CannyDetector_Demo.cpp(Canny边缘检测)

OpenCV2.4.10之samples_cpp_tutorial-code_learn-----ImgProc(图像处理)

本系列学习笔记参考自OpenCV2.4.10之 opencv\sources\samples\cpp\tutorial_code和 http://www.opencv.org.cn/opencvdoc/2.3.2/html/genindex.html       本博文将继续学习 OpenCV2.4.10中tutorial-code下的ImgProc,还有对于涉及到的知

OpenCV2.4.10之samples_cpp_tutorial-code_learn------安装配置与第一个Opencv程序

本系列学习笔记参考自OpenCV2.4.10之 opencv\sources\samples\cpp\tutorial_code和 http://www.opencv.org.cn/opencvdoc/2.3.2/html/genindex.html opencv作为一个开源的二维图形库,提供了一套完整的二维图像处理等相关算法的C/C++实现。自opencv2.0版

【kaldi】Kaldi tutorial翻译之Prerequisites(前提条件)-kaldi学习前必备梳理

本翻译仅供自己学习使用,不承担任何其他责任。水平有限拒绝转载。欢迎大家指出错误,共同学习。 我们假设本页的读者了解使用HMM-GMM进行语音识别的基础知识。在这里我们需要在线简明介绍的是:M. Gales and S. Young (2007).``The Application of Hidden Markov Models in Speech Recognition."