当前位置: 首页 > news >正文

Gobject tutorial 八

The GObject base class

Object memory management

Gobject的内存管理相关的API很复杂,但其目标是提供一个基于引用计数的灵活的内存管理模式。

下面我们来介绍一下,与管理引用计数相关的函数。

Reference Count

函数g_object_ref和g_object_unref的作用分别是增加和减少引用计数。g_clear_object函数是对g_object_unref的封装。

在调用g_object_new时,引用计数是1,1代表到目前为止使用此函数的使用者是此对象的唯一使用者,当引用计数是0时,对象的类结构体中的disopose()和finalize()会被调用,之后会调用g_type_free_instance()来释放对象实例结构体所占用的空间或者返回空间到此类型对象的对象池。如果对象的最后一个实例被释放,那么,对象的类结构体也会被销毁。

GObject销毁流程如下表:

Weak Reference

weak reference 的作用是监视对象的终止(finalization),g_object_weak_ref()会添加一个监视回调函数到对象,回调函数不会使对象的引用计数有任何变化,它只是在对象运行dispose的时候执行。

 Reference counts and cycles

GObject的销毁过程分为两个阶段,第一个阶段是在dispose函数中,dispose()会释放所有对其它成员对象的引用。第二个阶段是在finalize函数中,finalize()会释放对象本身所占用空间。在调用dispose后,调用finalize之前,对象的方法还能正常执行。

销毁过程分为两个阶段有益于打破循环引用。当检测到循环引用时,为了正常进行销毁工作,调用g_object_run_dipose就能打破循环。dispose能被多次执行,finalize只会执行一次。现在我们举例对这几句话进行说明。假如,对象A和对象B相互引用,现在我们检测到这样的情况,那么,现在需要销毁这两个对象,该怎么办呢?一种方式就是应用程序在操作释放一个对象时,调用g_object_run_dispose。

如果对象A全部释放所有对其他引用,当然也会释放对对象B的引用。如果这是最后一个对对象B的引用,那么A释放对B的引用,会导致unref 函数执行对象B的dispose, 进而导致B对象释放对对象A的引用,如果这也是对对象A的最后一个引用,对象B对对象A的引用的释放会导致第二次执行A的dispose。

Object properties

GObject的一个功能是能够通过set_property/get_property函数对对象属性进行操作。首先我们先举例说明属性如何定义的,以及在应用程序中如何使用。

首先,看一下定义。

// Implementationtypedef enum
{PROP_FILENAME = 1,PROP_ZOOM_LEVEL,N_PROPERTIES
} ViewerFileProperty;static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };static void
viewer_file_set_property (GObject      *object,guint         property_id,const GValue *value,GParamSpec   *pspec)
{ViewerFile *self = VIEWER_FILE (object);switch ((ViewerFileProperty) property_id){case PROP_FILENAME:g_free (self->filename);self->filename = g_value_dup_string (value);g_print ("filename: %s\n", self->filename);break;case PROP_ZOOM_LEVEL:self->zoom_level = g_value_get_uint (value);g_print ("zoom level: %u\n", self->zoom_level);break;default:/* We don't have any other property... */G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);break;}
}static void
viewer_file_get_property (GObject    *object,guint       property_id,GValue     *value,GParamSpec *pspec)
{ViewerFile *self = VIEWER_FILE (object);switch ((ViewerFileProperty) property_id){case PROP_FILENAME:g_value_set_string (value, self->filename);break;case PROP_ZOOM_LEVEL:g_value_set_uint (value, self->zoom_level);break;default:/* We don't have any other property... */G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);break;}
}static void
viewer_file_class_init (ViewerFileClass *klass)
{GObjectClass *object_class = G_OBJECT_CLASS (klass);object_class->set_property = viewer_file_set_property;object_class->get_property = viewer_file_get_property;obj_properties[PROP_FILENAME] =g_param_spec_string ("filename","Filename","Name of the file to load and display from.",NULL  /* default value */,G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);obj_properties[PROP_ZOOM_LEVEL] =g_param_spec_uint ("zoom-level","Zoom level","Zoom level to view the file at.",0  /* minimum value */,10 /* maximum value */,2  /* default value */,G_PARAM_READWRITE);g_object_class_install_properties (object_class,N_PROPERTIES,obj_properties);
}

再看看如何在应用中使用属性。

// UseViewerFile *file;
GValue val = G_VALUE_INIT;file = g_object_new (VIEWER_TYPE_FILE, NULL);g_value_init (&val, G_TYPE_UINT);
g_value_set_char (&val, 11);g_object_set_property (G_OBJECT (file), "zoom-level", &val);g_value_unset (&val);

之前,在介绍interface时,有个完整的例子使用过属性。Gobject tutorial 六-CSDN博客

现在我们介绍一下属性。

Properties

属性功能是由Gobject系统提供的。属性本身都是各种类型的数据,换句话说,对于单一的属性,它其实是一个类型的数据,可以是char *,也可以int,等等类型。属性是由对象实例维护,当然,这些对象实例都继承GObject。属性是按照名字来进行访问的,且一个实例中的对象,能够被其他实例访问。问题来了,这个“共享“是怎么做到的?我们后续会进行讨论。

在GObject中有很多方式可以设置和获取属性。

  • set方法有g_object_new、g_object_set, 后者是在应用中常用的方式。
  • get方法中应用最常用的方式是g_object_get.
GtkWindow *win;
win = g_object_new (GTK_TYPE_WINDOW, \"title", "Hello", \"default-width", 800, \"default-height", 600, NULL);

 另一个使用方式如下,

 

GtkWindow *win;
win = g_object_new (GTK_TYPE_WINDOW, NULL);
g_object_set (win, "title", "Good bye", NULL);

那么,如何获取呢,

GtkWindow *win;
char *title;
int width, height;win = g_object_new (GTK_TYPE_WINDOW, \"title", "Hello", \"default-width", 800, \"default-height", 600, NULL);
g_object_get (win, "title", &title, \"default-width", &width, \"default-height", &height, NULL);
g_print ("%s, %d, %d\n", title, width, height);
g_free (title);
 GParamSpec

说到属性,我们不得不对GParamSpec进行说明。GParamSpec是一个fundamental object, 它与GObject并无父子关系,它的作用是保存参数的信息,当然此处的参数也可以是属性。

我们看看它在属性注册过程中的作用。

/*gtk 4.8.2 demo3widget.c*/
static void
demo3_widget_class_init (Demo3WidgetClass *class)
{GObjectClass *object_class = G_OBJECT_CLASS (class);
......object_class->dispose = demo3_widget_dispose;object_class->set_property = demo3_widget_set_property;object_class->get_property = demo3_widget_get_property;......g_object_class_install_property (object_class, PROP_PAINTABLE,g_param_spec_object ("paintable", "Paintable", "Paintable",GDK_TYPE_PAINTABLE,G_PARAM_READWRITE));g_object_class_install_property (object_class, PROP_SCALE,g_param_spec_float ("scale", "Scale", "Scale",0.0, 10.0, 1.0,G_PARAM_READWRITE));......
}

注册 属性是通过函数g_object_class_install_property完成的,新类型在注册时,会实现自己的set_property/get_property函数,如上面的demo3_widget_set_property/demo3_widget_get_property。

g_object_class_install_property函数的声明如下,

void        g_object_class_install_property   (GObjectClass   *oclass,guint           property_id,GParamSpec     *pspec)

既然在注册属性过程中,GparamSpec是必须的,那么,就有必要对生成GParamSpec的函数进行说明,我们以上例中的g_param_spec_float为例,看看Glib的说明。

/*** g_param_spec_float:* @name: canonical name of the property specified* @nick: (nullable): nick name for the property specified* @blurb: (nullable): description of the property specified* @minimum: minimum value for the property specified* @maximum: maximum value for the property specified* @default_value: default value for the property specified* @flags: flags for the property specified** Creates a new #GParamSpecFloat instance specifying a %G_TYPE_FLOAT property.** See g_param_spec_internal() for details on property names.** Returns: (transfer full): a newly created parameter specification*/
GParamSpec*
g_param_spec_float (const gchar *name,const gchar *nick,const gchar *blurb,gfloat	 minimum,gfloat	 maximum,gfloat	 default_value,GParamFlags	 flags)
 Overriding set_property and get_property class methods

重写set_property 、get_property的过程如下:

 对于不同的对象实例,属性值是不同的,因此,属性值是存储在对象的实例中的。具体这是怎么做的呢。我们以上例中的demo3_widget_set_property为例进行说明。

static void
demo3_widget_set_property (GObject      *object,guint         prop_id,const GValue *value,GParamSpec   *pspec)
{Demo3Widget *self = DEMO3_WIDGET (object);switch (prop_id){case PROP_PAINTABLE:g_clear_object (&self->paintable);self->paintable = g_value_dup_object (value);gtk_widget_queue_resize (GTK_WIDGET (object));break;case PROP_SCALE:self->scale = g_value_get_float (value);gtk_widget_queue_resize (GTK_WIDGET (object));break;default:G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);break;}
}

可以看到需要设置的属性值value,保存在self->paintable、self->scale中。Demo3Widget的定义如下,

struct _Demo3Widget
{GtkWidget parent_instance;GdkPaintable *paintable;float scale;GtkWidget *menu;
};
Notify signal

还有一个重要的问题就是,当设置属性后,GObject会发出“notify"信号。如果你在程序中给信号链接了处理函数,你就能进行后续操作。notify信号在链接处理函数时,是有格式要求的。如下:

g_signal_connect (G_OBJECT (d1), "notify::value", G_CALLBACK (notify_cb), NULL);

上面示例中“notify::value”中的value需要替换成属性名。如果不设置value,那么,对象的任何属性被设置,回调函数都会执行。 注意,我们这里说,当属性被设置时,会发出notify 信号,那么,问题来了,我为属性设置相同的值,会不会有notify信号呢?答案是,会有的。那如果我想只在信号值发生改变时,才受到notify信号,该怎么办呢?这种情况下,首先我们在调用函数生成GParamSpec时,为函数设置属性G_PARAM_EXPLICIT_NOTIFY标记,具体来说,对于上面提到的函数g_param_spec_float为例,设置其最后的参数flag为G_PARAM_EXPLICIT_NOTIFY。其次需要在属性发生变化时,手动调用函数g_object_notify_by_pspec来发送notify 信号。

 

相关文章:

Gobject tutorial 八

The GObject base class Object memory management Gobject的内存管理相关的API很复杂,但其目标是提供一个基于引用计数的灵活的内存管理模式。 下面我们来介绍一下,与管理引用计数相关的函数。 Reference Count 函数g_object_ref和g_object_unref的…...

DDMA信号处理以及数据处理的流程---cfar检测

Hello,大家好,我是Xiaojie,好久不见,欢迎大家能够和Xiaojie一起学习毫米波雷达知识,Xiaojie准备连载一个系列的文章—DDMA信号处理以及数据处理的流程,本系列文章将从目标生成、信号仿真、测距、测速、cfar检测、测角、目标聚类、目标跟踪这几个模块逐步介绍,这个系列的…...

【机器学习】从理论到实践:决策树算法在机器学习中的应用与实现

📝个人主页:哈__ 期待您的关注 目录 📕引言 ⛓决策树的基本原理 1. 决策树的结构 2. 信息增益 熵的计算公式 信息增益的计算公式 3. 基尼指数 4. 决策树的构建 🤖决策树的代码实现 1. 数据准备 2. 决策树模型训练 3.…...

Zookeeper 集群节点故障剔除、切换、恢复原理

Zookeeper 集群节点故障剔除、切换、恢复原理 zookeeper 集群节点故障时,如何剔除节点,如果为领导节点如何处理,如何进行故障恢 复的,实现原理? 在 Zookeeper 集群中,当节点故障时,集群需要自动剔除故障节点并进行故障恢复,确保集群的高 可用性和一致性。具体来说,…...

解决帝国cms栏目管理拼音乱码的问题

帝国CMS7.5版本utf-8版网站后台增加栏目生成乱码的问题怎么解决 1、需要改一个函数,并且增加一个处理文件,方法如下: 修改e/class/connect.php文件,找到ReturnPinyinFun函数,如未修改文件在4533-4547行,将…...

Git快速入门

一 快速使用 1.1 初始化 什么是版本库呢?版本库又名仓库,可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史&#xff0…...

【18.0】JavaScript---事件案例

【18.0】JavaScript—事件案例 【一】开关灯事件 【介绍】设置一个按钮,按下按钮触发事件,来回切换圆形图片的颜色 【分析】 图片设置:设置成圆形的图片背景颜色:设置红绿两个颜色,来回切换按钮设置:点击…...

推荐系统三十六式学习笔记:原理篇.矩阵分解12|如果关注排序效果,那么这个模型可以帮到你

目录 矩阵分解的不足贝叶斯个性化排序AUC构造样本目标函数训练方法 总结 矩阵分解在推荐系统中的地位非常崇高。它既有协同过滤的血统,又有机器学习的基因,可以说是非常优秀了;但即便如此,传统的矩阵分解无论是在处理显式反馈&…...

Kafka之ISR机制的理解

文章目录 Kafka的基本概念什么是ISRISR的维护机制ISR的作用ISR相关配置参数同步过程示例代码总结 Kafka中的ISR(In-Sync Replicas同步副本)机制是确保数据高可用性和一致性的核心组件。 Kafka的基本概念 在Kafka中,数据被组织成主题&#xf…...

如何设计一个点赞系统

首先我们定义出一个点赞系统需要对外提供哪些接口: 1.用户对特定的消息进行点赞; 2.用户查看自己发布的某条消息点赞数量以及被哪些人赞过; 3.用户查看自己给哪些消息点赞过; 这里假设每条消息都有一个message_id, 每一个用户都…...

对象存储测试工具-s3cmd

一、环境安装 官网:https://s3tools.org/s3cmd 下载安装包:https://s3tools.org/download GitHub:https://github.com/s3tools/s3cmd/releases 本文安装包:https://github.com/s3tools/s3cmd/releases/download/v2.0.2/s3cmd-2.0…...

OpenCV--图像色彩空间及转换

图像色彩空间及转换 python代码和笔记 python代码和笔记 import cv2 色彩空间,基础:RGB或BGR OpenCV中: 一、HSV(HSB):用的最多, Hue:色相-色彩(0-360),红色:0,绿色&…...

RIP解决不连续子网问题

#交换设备 RIP解决不连续子网问题 一、不连续子网的概念 相同主网下的子网,被另一个主网分割,例如下面实验拓扑在某公司的网络整改项目中,原先R1 和RS 属于同一主网络 10.0.0.0/8,现被 R2、R3、R4 分离,整网采用了 …...

动态轮换代理IP是什么?有什么用?

如果您要处理多个在线帐户,选择正确的代理类型对于实现流畅的性能至关重要。但最适合这项工作的代理类型是什么? 为了更好地管理不同平台上的多个账户并优化成本,动态住宅代理IP通常作用在此。 一、什么是轮换代理? 轮换代理充当…...

MAC配置VScode中C++项目debug环境

文章目录 配置步骤问题解决Unable to start debugging. LLDB exited unexpectedly with exit code 137 (0x89). 配置步骤 在Mac上配置VS Code以进行C调试涉及几个步骤: 安装必要的工具: 确保您已经安装了Visual Studio Code和C插件。 检查是否安装了Clang&#xf…...

PostgreSQL源码分析——CREATE CAST

CREATE CAST源码分析 CREATE CAST用法 CREATE CAST —— 定义一个用户自定义的类型转换 用法如下: CREATE CAST (source_type AS target_type)WITH FUNCTION function_name [ (argument_type [, ...]) ][ AS ASSIGNMENT | AS IMPLICIT ]CREATE CAST (source_type…...

解锁5G新营销:视频短信的优势与全方位推广策略

随着5G时代的全面来临,企业的数字化转型步伐日益加快,视频短信作为新兴的数字营销工具,正逐步展现出其巨大的潜力。视频短信群发以其独特的形式和内容,将图片、文字、视频、声音融为一体,为用户带来全新的直观感受&…...

视频监控平台功能:国外的硬盘录像机NVR通过ISUP协议(原ehome协议)接入AS-V1000视频平台

目录 一、背景说明 二、ISUP协议介绍 1、海康ISUP协议概述 2、ISUP协议支持主码流和子码流切换 (1)灵活配置和个性化 (2)适应不同网络带宽,提高使用体验 3、海康ehome相关文章 三、ISUP协议接入说明 1、平台侧…...

PostgreSQL查询用户

在 PostgreSQL 中,可以通过查询系统表来确定当前用户是否是超级管理员(超级用户)。具体来说,可以使用 pg_roles 系统表,该表包含数据库中所有角色的信息。 以下是查询当前用户是否是超级用户的 SQL 语句: …...

力扣1539.第k个缺失的正整数

力扣1539.第k个缺失的正整数 占位运算 只要n<k &#xff0c;k;最终k就是结果 class Solution {public:int findKthPositive(vector<int>& arr, int k) {for(int n : arr){if(n < k) k ;else break;}return k;}};...

如何快速解决屏幕适配问题

下面将利用postcss插件快速解决屏幕适配问题。仅用少量代码&#xff0c;新手均可快速使用。 Step1. 安装 npm install postcss-px-to-viewport-8-plugin --save-dev Step2. 新建 postcss.config.js 文件&#xff0c;做基础配置 module.exports {plugins: {postcss-px-to-v…...

Go基础编程 - 09 - 通道(channel)

通道&#xff08;channel&#xff09; 1. 声明2. channel的操作3. 无缓冲通道4. 有缓冲通道5. 如何优雅的从通道循环取值6. 单向通道7. 异常总结 上一篇&#xff1a;结构体 Go语言的并发模式&#xff1a;不要通过共享内存来通信&#xff0c;而应该通过通信来共享内存。 Go语言…...

[SAP ABAP] 数据类型

1.基本数据类型 示例1 默认定义的基本数据类型是CHAR数据类型 输出结果: 示例2 STRING数据类型用于存储任何长度可变的字符串 输出结果: 示例3 DATE数据类型用于存储日期信息&#xff0c;并且可以存储8位数字 输出结果: 提示Tips&#xff1a;日期和时间类型的变量可以直接进…...

什么是Vue开发技术

概述 Vue.js 是一个用于构建用户界面的渐进式框架&#xff0c;它设计得非常灵活&#xff0c;可以轻松地被集成到任何项目中。 vue是视图的发音&#xff0c;其目的是帮助开发者易于上手&#xff0c;提供强大的功能构建复杂的应用程序 示例 以下是vue基本的语法概述 声明式渲…...

【QT】

通信服务端实现 widget.h文件 #ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QTcpServer>//服务器类 #include <QMessageBox>//消息 #include <QTcpServer> #include <QList> #include <QTcpSocket> QT_BEGIN_NAMESPAC…...

【转载】使用 .NET Upgrade Assistant(升级助手)升级 .NET 老旧版本项目

使用 .NET Upgrade Assistant&#xff08;升级助手&#xff09;升级 .NET 老旧版本项目&#xff1a;https://blog.csdn.net/ChaITSimpleLove/article/details/134711604...

SpringBoot如何自定义启动Banner 以及自定义启动项目控制台输出信息 类似于若依启动大佛 制作教程

前言 Spring Boot 项目启动时会在控制台打印出一个 banner&#xff0c;下面演示如何定制这个 banner。 若依也会有相应的启动动画 _ooOoo_o8888888o88" . "88(| -_- |)O\ /O____/---\____. \\| |// ./ \\||| : |||// \/ _||||| -:- |||||- \| | \\…...

访问控制列表(Access Control Lists,ACL)与哈希查找的爱恨情怨

访问控制列表&#xff08;Access Control Lists&#xff0c;ACL&#xff09;与哈希查找 什么是访问控制列表ACL&#xff1f;直接说ACL是干啥的ACL概念为什么需要ACLACL类型ACL匹配机制使用例子 哈希查找什么是哈希查找&#xff1f;哈希查找的基本原理哈希查找的步骤 哈希查找在…...

一文讲清楚分销裂变是什么?怎么做好分销裂变?【附案例】

在数字化营销日益盛行的今天&#xff0c;分销裂变作为一种高效的推广手段&#xff0c;受到了越来越多企业的青睐。那么&#xff0c;分销裂变究竟是什么&#xff1f;我们又该如何做好分销裂变呢&#xff1f;林叔将从定义、方法以及案例分析三个方面进行阐述。 一、分销裂变是什…...

Mybatis Plus 详解 IService、BaseMapper、自动填充、分页查询功能

结构直接看目录 前言 MyBatis-Plus 是一个 MyBatis 的增强工具&#xff0c;在 MyBatis 的基础上只做增强不做改变&#xff0c;为简化开发、提高效率而生。 愿景 我们的愿景是成为 MyBatis 最好的搭档&#xff0c;就像 魂斗罗 中的 1P、2P&#xff0c;基友搭配&#xff0c;效…...

做英文企业网站多钱钱/燃灯seo

问题描述&#xff1a;八皇后不能相互攻击&#xff0c;即&#xff0c;八个皇后不能同行&#xff0c;同列&#xff0c;不同在同一条对角线上&#xff0c; 对角线又可以分为左对角线和右对角线 左对角线上满足&#xff1a;i-j7都相等(i,j分别是一维和二维的坐标) 右对角线满足&…...

微信网站开发测试号/极速建站网站模板

打开CMD.exe命令行窗口 。通过chcp命令改变代码页&#xff0c;chcp 65001。&#xff08;65001为UTF-8的代码页&#xff09;修改窗体属性&#xff0c;改变字体&#xff0c;将字体修改为True Type字体“Lucida Console”。改变命令行窗体大小或者重启命令行窗体尝试操作。...

雄安智能网站建设电话/企业宣传片

位运算符&#xff08;内存中的位数进行操作&#xff0c;二进制比特位比一般语法乘2要快一些&#xff09;&#xff1a;优化我们的算法&#xff0c;提高我们的效率。 位于&#xff1a;& 位或&#xff1a;| 异或&#xff1a;^ 相异得1&#xff0c;相同得0 位非&#xff1a;~ …...

网站banner图做多大/seo黑帽教程视频

从来没有机会触摸新西兰的脉搏&#xff0c;这次有机会趁着亚太区管理层会议前往&#xff0c;有些神往&#xff0c;虽然可能会觉得比较疲劳&#xff0c;因为从美国出差回到上海是2月3日了&#xff0c;2月4日就要从上海飞新西兰。但是&#xff0c;对这片土地的陌生使得仍然充满了…...

高碑店住房和城乡建设局网站/seo产品优化推广

原文&#xff1a;http://coolketang.com/staticCoding/5a990cf30b61607bf6cdcfdc.html 1. 本节课将为您演示如何使用不同设备类型的模拟器。双击打开之前创建的项目模板。 2. 点击[编译并运行]按钮&#xff0c;打开模拟器并预览当前项目。 3. 当您向苹果提交应用时&#xff0c;…...

山西网站开发公司/湖南seo优化哪家好

单元格合并着实让人为难&#xff01; 使用的dev 的GridControl控件&#xff0c;实现数据绑定很方便&#xff0c;但是在网上查怎么都没有找到如何实现单元格的合并。所以只好作罢。 然后计划采用FlexCell&#xff0c;但是是付费的。使用了一下和Excel差类似&#xff0c;实现的样…...