sec2-GObject

news2024/11/20 4:53:11

1 类和实例

GObject实例用函数g_object_new创建。GObject不仅仅有实例,也有类。

  • 一个GObject类在第一次访问g_object_new时候创建,只有有一个GObject类存在。
  • GObject实例在任何时候访问g_object_new都会被创建,所以就会创建更多GObject实例。

从广义上讲,GObject意味着对象,这个对象包括它的类和实例。在狭义上将,GObject是一个C结构体的定义。

typedef struct _GObject GObject;
struct _GObject{
	GTypeInstance g_type_instance;
	/*< private >*/
	guint ref_count; /* (atomic) */
	GData *qdata;
};
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程序是在GLib源文件里面,可以从GNOME下载GLib源文件。
有个示例程序在src/misc目录里面,一个示例程序是example1.c,它的代码如下:

 1 #include <glib-object.h>
 2 
 3 int
 4 main (int argc, char **argv) {
 5   GObject *instance1, *instance2;
 6   GObjectClass *class1, *class2;
 7   
 8   instance1 = g_object_new (G_TYPE_OBJECT, NULL);
 9   instance2 = g_object_new (G_TYPE_OBJECT, NULL);
10   g_print ("The address of instance1 is %p\n", instance1);
11   g_print ("The address of instance2 is %p\n", instance2);
12 
13   class1 = G_OBJECT_GET_CLASS (instance1);
14   class2 = G_OBJECT_GET_CLASS (instance2);
15   g_print ("The address of the class of instance1 is %p\n", class1);
16   g_print ("The address of the class of instance2 is %p\n", class2);
17 
18   g_object_unref (instance1);
19   g_object_unref (instance2);
20 
21   return 0;
22 }
23 
  • 5-6:instance1和instance2是指向GObject实例的指针,class1和class2指向实例的一个类(同一个类)。

  • 8-11:函数g_object_new创建一个GObject实例,GObject实例是一大块内存,这个内存里面有结构体(struct _GObject)。G_TYPE_OBJECT参数是一个GObject类型。这个类型是不同于C语言中的char或者int类型。Type系统是一GObject系统的基础。每个数据类型(比如GObject)都必须注册到类型系统。类型系统具有一系列用于注册的函数,这些函数的作用是为了注册。如果这些函数的某一个被访问,这时,这个类型系统会确定Gtype这个对象的类型值,然后返回它给函数访问者。在我的计算机上(主要依赖于计算机硬件,不同硬件可能long长度不一样),GType是一个无符号长整形(unsigned long)。g_object_new分配GObject-sized大小的内存,并返回指向内存顶部地址的指针。创建后,该程序显示实例的地址。
    请添加图片描述

  • example代码运行结果:

The address of instance1 is 0x561ad5205a00
The address of instance2 is 0x561ad5205a20
The address of the class of instance1 is 0x561ad5205830
The address of the class of instance2 is 0x561ad5205830

两个实例instance1和instance2的位置是不同的,每个实例有它自己的内存。class1和class2的位置是相同的,两个实例共享同一个类。
在这里插入图片描述

2 引用计数(Reference Count)

GObject实例有自己的内存。它们是在创建时由系统分配的。如果它变得无用,就必须释放内存。然而,我们如何判断它是否无用呢? GObject系统提供引用计数去解决这个问题。实例由其他对象或主程序创建和使用。也就是说,实例被引用。如果实例被A和B引用,那么引用的编号为2。这个数字称为引用计数。让我们想象一个这样的场景:

  • A调用g_object_new并拥有一个实例G。A引用G,因此G的引用计数为1。
  • B也想使用G。B调用g_object_ref并将引用计数增加了1。现在引用计数是2。
  • A不再使用G。A调用g_object_ref并将引用计数减少1。现在引用计数是1
  • B不再使用G。B调用g_object_ref并将引用计数减少1。现在引用计数是0
  • 因为引用计数为零,G知道没有人引用它。G开始自己完成这个过程。G消失,内存被释放。

程序example2.c是基于上述场景的:

 1 #include <glib-object.h>
 2 
 3 static void
 4 show_ref_count (GObject *instance) {
 5   if (G_IS_OBJECT (instance))
 6     /* Users should not use ref_count member in their program. */
 7     /* This is only for demonstration. */
 8     g_print ("Reference count is %d.\n", instance->ref_count);
 9   else
10     g_print ("Instance is not GObject.\n");
11 }
12 
13 int
14 main (int argc, char **argv) {
15   GObject *instance;
16   
17   instance = g_object_new (G_TYPE_OBJECT, NULL);
18   g_print ("Call g_object_new.\n");
19   show_ref_count (instance);
20   g_object_ref (instance);
21   g_print ("Call g_object_ref.\n");
22   show_ref_count (instance);
23   g_object_unref (instance);
24   g_print ("Call g_object_unref.\n");
25   show_ref_count (instance);
26   g_object_unref (instance);
27   g_print ("Call g_object_unref.\n");
28   show_ref_count (instance);
29   
30   return 0;
31 }
32 

代码执行结果如下:

Call g_object_new.
Reference count is 1.
Call g_object_ref.
Reference count is 2.
Call g_object_unref.
Reference count is 1.
Call g_object_unref.
Instance is not GObject.

  1. g_object_new创建一个新的GObject实例,并将其引用计数设置为1。
  2. g_object_ref将引用计数增加1。
  3. g_object_unref使引用计数减少1。如果引用计数降为零,实例将自行销毁。

3 初始化和销毁过程

GObject初始化和销毁的实际过程非常复杂。以下是不含细节的简单描述。

3.1 初始化

  1. 用类型系统注册GObject类型。这是在调用main函数之前在GLib初始化过程中完成的。(如果编译器是gcc,则使用__attribute__ (constructor) )来获得初始化函数。参考GCC手册)
  2. 为GObjectClass和GObject结构分配内存。
  3. 初始化GObjectClass结构内存。这个内存将是GObject的类。
  4. 初始化GObject结构内存。这个内存将是GObject的实例。

3.2 销毁

  销毁GObject实例。实例的内存被释放。GObject类型是静态类型。静态类型从不破坏它的类。因此,即使被销毁的实例是最后一个实例,类仍然存在。
  当您编写代码来定义GObject的子对象时,理解上面的过程很重要。后面的部分将解释详细的过程。

翻译自GObject tutorial

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/124594.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【剧前爆米花--爪哇岛寻宝】String类型构造,修改的底层逻辑与StringBuilder和StringBuffer的关系

作者&#xff1a;困了电视剧 专栏&#xff1a;《JavaSE语法与底层详解》 文章分布&#xff1a;这是一篇关于String类型及其底层构造的文章&#xff0c;如有疏漏&#xff0c;欢迎大佬指正&#xff01; String对象的创建 字符串的用法比较多&#xff0c;所以String类提供的构造方…

算法复杂度 O(1),O(n),O(logn),O(nlogn)的区别

算法复杂度分为时间复杂度和空间复杂度 时间复杂度是指执行这个算法所需要的计算工作量空间复杂度是指这个算法所需要的内存空间 1.对于一个循环&#xff0c;假设循环体的时间复杂度为O(n),循环次数为n&#xff0c;则这个循环的时间复杂度为O(n*1)。 void aFunc(int n) {for…

嵌入式终端的以太网系统简析

一 初识以太网电路 从硬件的角度看&#xff0c;以太网接口电路主要由 MAC&#xff08;Media Access Control&#xff09;控制器和物理层接口 PHY&#xff08;Physical Layer&#xff09;两大部分构成&#xff0c;一般一个嵌入式终端系统的以太网硬件抽象 如下&#xff1a; 1 网…

数字孪生教学楼3d可视化系统功能介绍

目前&#xff0c;校园教学楼运维管理阶段面临的主要难题有&#xff1a;数据采集不全、数据各自为阵的数据孤岛现象严重&#xff1b;系统的集成度低&#xff0c;缺乏统一、有效的运行维护处理中心平台&#xff1b;能耗巨大&#xff0c;不符合绿色建筑要求&#xff0c;未形成有效…

做了多年的Android开发,自己是否有擅长领域?(Framework 篇)

前言 如今Android 开发行业的招聘需求可谓是越来越高了&#xff0c;如果你想入大厂工作&#xff0c;学历还只是他们的基础入门的门槛&#xff0c;他们不仅要看学历还得看你是否在某块技术领域有着过硬的实力。比如&#xff1a;APP性能优化、Framework底层原理、音视频、APP架构…

数字验证学习笔记——SystemVerilog芯片验证17 ——数组约束

一、数组约束 1.1 数组的属性约束 多数情况下&#xff0c;数组的大小应该给定范围&#xff0c;防止生成过大体积的数组或者空数组此外还可以在约束中结合数组的其他方法sum&#xff08;&#xff09;&#xff0c;product&#xff08;&#xff09;&#xff0c;and&#xff08;&a…

Ansys Zemax | 如何在 OpticStudio 中模拟人眼

本文是人眼模型的一个案例研究&#xff0c;并提供了更高级的序列模式建模技术的演示。我们将在OpticStudio中使用Liou & Brennan 1997眼睛模型创建人眼模型。在OpticStudio中成功生成这个眼睛模型后&#xff0c;我们将使用它来设计一个自由形式的渐进眼镜镜片。 下载 联系…

正大国际期货:2022年各行业顶级富豪身价大洗牌

2022年各行业顶级富豪身价大洗牌 富豪身价较2021年年底变动幅度涨跌幅 行业&#xff1a;加密货币&#xff0c;币安创始人&#xff1a;赵长鹏816%&#xff0c;身价174亿美元 行业&#xff1a;基建、大宗商品&#xff0c;阿达尼集团创始人&#xff1a;高塔姆阿达尼210%&#x…

Linux下Python脚本的编写(二)

今天试着把两个shell小脚本转化成Python版本 一. 脚本1 判断所接的nvme 在哪个CPU上 #!/bin/bash lscpu |grep -i node for nvme in nvme list|sed 1,2d|awk {print $1}|awk -F "/" {print $NF} doecho $nvmebusid$(readlink -f /sys/block/$nvme |cut -d / -f 6)ec…

【解决】VMware虚拟机中ubuntu系统联网问题——以桥接模式解决

问题描述 由于需要通过笔记本的蓝牙与外接设备进行通信&#xff0c;我使用的是无线网。所以需要使用VMware中提供的桥接模式&#xff0c;借助笔记本的无线网卡进行联网&#xff0c;之前设置过一次&#xff0c;能够正常运行&#xff0c;但是关机后&#xff0c;可能加载的快照不同…

维视智造成为苏州市人工智能行业协会首届会员单位

近日&#xff0c;以“智者相偕聚势赋能”为主题的苏州市人工智能行业协会一届一次会员大会暨成立大会在苏州举行&#xff0c;来自全市200多家人工智能相关单位的代表以及人工智能领域的知名学者、产业专家、企业家参加了会议。维视智造作为协会的首届会员&#xff0c;与苏州市工…

2022/12/28总结

今天AC了一道题&#xff08;后面的题目对我来说好难&#xff0c;刷不动了&#xff09; P2895 [USACO08FEB]Meteor Shower S P2895 [USACO08FEB]Meteor Shower S_lxh0113的博客-CSDN博客 学的新知识&#xff1a; dijkstra算法 dijkstra算法是求最短路径的算法。相比较于flo…

【真干货】Activiti7工作流如何使用?看这里

一. 前言 近日文哥有个毕业学员在公司开发时遇到了工作流的相关业务场景。在这里&#xff0c;文哥给大家精心准备了以Activiti为代表的工作流简单使用教程&#xff0c;希望能给有需要的小伙伴们一些帮助。下面我们就来开始介绍Activiti工作流的基本使用情况。 二. Activiti工…

利器 | Java 接口自动化测试首选方案:REST Assured 实践 (一)

在 REST Assured 的官方 GitHub 上有这样一句简短的描述&#xff1a; Java DSL for easy testing of REST services 简约的 REST 服务测试 Java DSL REST Assured 官方的 README 第一句话对进行了一个优点的概述&#xff0c;总的意思表达的就是简单好用。那么 REST Assured 有…

dolphinscheduler 调用shell脚本执行sql

1. 资源中心--创建文件 脚本&#xff1a; #!/bin/bash hive <<EOF alter table app.app_bi_test drop partition (dayid$1); insert overwrite table app.app_bi_test partition(dayid) select a.Ccode,a.inCcode ,a.Cname ,$1,COALESCE(b.num,0) ,COALESCE(c.c_num…

以前的任何一个行业只要与互联网技术产生联系,便焕发生机与活力

事实上&#xff0c;以往&#xff0c;我们所经历的那个互联网玩家频出的年代&#xff0c;其实就是一个以互联网技术为主导的年代。在那样一个年代里&#xff0c;互联网技术几乎是解决一切痛点和难题的万能解药&#xff0c;几乎是破解一切行业痛点和难题的杀手锏。任何一个行业&a…

XXE渗透与攻防(一)

目录 前言 XML基础知识 XML用途 XML内容 XML格式要求 XML格式校验 不同语言支持的协议 完整的XML内容 什么是XXE 案列演示 盲打-DNSLog XXE 防御 前言 现在许多不同的客户端技术都可以使用XMl向业务应用程序发送消息&#xff0c;为了使应用程序使用自定义的XML消…

高压放大器在介电泳分选的应用

实验名称&#xff1a;基于高压放大器的介电泳分选 研究方向&#xff1a;滴液分选 测试原理&#xff1a; 在非均匀电场中&#xff0c;介电体表面感生出的正负电荷处于不同场强的位置上在它受到的合力大于一定值时就会被拉向强电场方向。 测试设备&#xff1a;ATA-7030高压放大器…

类与对象(下)

类与对象构造函数构造函数体赋值初始化列表explicit关键字static成员概念特性友元友元函数友元类内部类匿名对象拷贝对象时的一些编译器优化构造函数 构造函数体赋值 在创建对象时&#xff0c;编译器通过调用构造函数&#xff0c;给对象中各个成员变量一个合适的初始值 clas…

勃仔诞生记:Hubbleverse哈勃元宇宙的起源故事

欢迎来到Hubbleverse &#x1f30d; 关注我们 关注宇宙新鲜事 &#x1f4cc; 预计阅读时长&#xff1a;9分钟 本文仅代表作者个人观点&#xff0c;不代表平台意见&#xff0c;不构成投资建议。 想象一个属于你的世界&#xff0c;一个资源丰富的世界&#xff0c;你可以在其中…