Gobject tutorial 十一

参考:GObject – 2.0

Generic Value Container

GValue结构体是一个变量容器,它包含一个类型成员和类型对应的值。其定义如下:

/*** GValue:* * An opaque structure used to hold different types of values.** The data within the structure has protected scope: it is accessible only* to functions within a #GTypeValueTable structure, or implementations of* the g_value_*() API. That is, code portions which implement new fundamental* types.** #GValue users cannot make any assumptions about how data is stored* within the 2 element @data union, and the @g_type member should* only be accessed through the G_VALUE_TYPE() macro.*/
struct _GValue
{/*< private >*/GType		g_type;/* public for GTypeValueTable methods */union {gint	v_int;guint	v_uint;glong	v_long;gulong	v_ulong;gint64      v_int64;guint64     v_uint64;gfloat	v_float;gdouble	v_double;gpointer	v_pointer;} data[2];
};

 GVaule 变量只能在初始化后使用,初始化函数是g_value_init()。用完之后需要调用g_value_unset()来进行资源释放。

基础的操作(例如free、copy)都有GTypeValueTable中的函数负责,GTypeValueTable是与GValue中的g_type对应。GValue的其他操作(例如,类型转换)都有接口提供。

我们先看看GTypeValueTable的定义。

struct _GTypeValueTable
{GTypeValueInitFunc value_init;GTypeValueFreeFunc value_free;GTypeValueCopyFunc value_copy;GTypeValuePeekPointerFunc value_peek_pointer;const gchar *collect_format;GTypeValueCollectFunc collect_value;const gchar *lcopy_format;GTypeValueLCopyFunc lcopy_value;
};

那,GValue中的g_type与GTypeValueTable是如何对应起来的呢?

我们来看看GLib的基本类型gchar,它是怎么对应二者的。

  /* G_TYPE_CHAR / G_TYPE_UCHAR*/{static const GTypeValueTable value_table = {value_init_long0,		/* value_init */NULL,			/* value_free */value_copy_long0,		/* value_copy */NULL,			/* value_peek_pointer */"i",			/* collect_format */value_collect_int,	/* collect_value */"p",			/* lcopy_format */value_lcopy_char,		/* lcopy_value */};info.value_table = &value_table;type = g_type_register_fundamental (G_TYPE_CHAR, g_intern_static_string ("gchar"), &info, &finfo, 0);g_assert (type == G_TYPE_CHAR);type = g_type_register_fundamental (G_TYPE_UCHAR, g_intern_static_string ("guchar"), &info, &finfo, 0);g_assert (type == G_TYPE_UCHAR);}GType
g_type_register_fundamental (GType                       type_id,const gchar                *type_name,const GTypeInfo            *info,const GTypeFundamentalInfo *finfo,GTypeFlags			 flags)
{......
node = type_node_fundamental_new_W (type_id, type_name, finfo->type_flags);
......if (check_type_info_I (NULL, NODE_FUNDAMENTAL_TYPE (node), type_name, info))type_data_make_W (node, info,check_value_table_I (type_name, info->value_table) ? info->value_table : NULL);
......
}static TypeNode*
type_node_fundamental_new_W (GType                 ftype,const gchar          *name,GTypeFundamentalFlags type_flags)
{
......node = type_node_any_new_W (NULL, ftype, name, NULL, type_flags);......return node;
}static TypeNode*
type_node_any_new_W (TypeNode             *pnode,GType                 ftype,const gchar          *name,GTypePlugin          *plugin,GTypeFundamentalFlags type_flags)
{
......node = g_malloc0 (node_size);if (!pnode)					      /* offset fundamental types */{
node = G_STRUCT_MEMBER_P (node, SIZEOF_FUNDAMENTAL_INFO);static_fundamental_type_nodes[ftype >> G_TYPE_FUNDAMENTAL_SHIFT] = node;type = ftype;.....}return node;
}

上述代码分析了 g_type_register_fundamental中,ftype与node 的关系,接下来,我们看看node 与GTypeValueTable的关系,这就需要分析g_type_register_fundamental中的另一部分代码。

static void
type_data_make_W (TypeNode              *node,const GTypeInfo       *info,const GTypeValueTable *value_table)
{
......*vtable = *value_table;......}

通过分析,类型GType与GTypeValueTable是通过数组static_fundamental_type_nodes关联起来的。即,通过TypeNode联系起来的。

static TypeNode		*static_fundamental_type_nodes[(G_TYPE_FUNDAMENTAL_MAX >> G_TYPE_FUNDAMENTAL_SHIFT) + 1] = { NULL, };

那么GValue与TypeNode的关系是什么样的呢?

这个问题,需要查看g_value_init函数才能解决。

GValue*
g_value_init (GValue *value,GType   g_type)
{
......value_table = g_type_value_table_peek (g_type);
......value_meminit (value, g_type);
...
}static inline void		/* keep this function in sync with gvaluecollector.h and gboxed.c */
value_meminit (GValue *value,GType   value_type)
{value->g_type = value_type;memset (value->data, 0, sizeof (value->data));
}

通过上述代码,可以知道,在调用g_value_init初始化GVaule变量后,变量的g_type是固定的,以后可以通过g_type,调用函数g_type_value_table_peek,通过数组static_fundamental_type_nodes找到变量类型对应的 GTypeValueTable。

Boxed Types

boxed type是一个通用的、可对任意C结构进行封装的机制。对于boxed type,GObject的类型系统只关心这个结构体如何被复制(对应GBoxedCopyFunc)和如何被释放(对应GBoxedFreeFunc)。

使用boxed type,使得对任意类型的数据结构的处理方式变得统一,可以进行统一方式的复制、释放,对外界的统一表现形式。进而,所有可以进行boxed type处理的数据类型都可以作为GValue结构中的data成员(关键是GValue data数组中有个gpointer),这样,可以对更广范围的数据类型进行多态处理,因此,可以使更多的数据类型可以作为Gobject的属性使用。

所有的boxed type 都继承自G_TYPE_BOXED,这个基础类型。

值得注意的是boxed types 不是深度可继承的,这就是说,你不能对继承自另外一个boxed type的boxted type进行注册。

Registering a new boxed type

我们通过实例来看看怎么注册。

typedef struct _MyBoxed MyBoxed;struct _MyBoxed
{gint ivalue;gchar *bla;
};static gpointer
my_boxed_copy (gpointer orig)
{MyBoxed *a = orig;MyBoxed *b;b = g_slice_new (MyBoxed);b->ivalue = a->ivalue;b->bla = g_strdup (a->bla);return b;
}static gint my_boxed_free_count;static void
my_boxed_free (gpointer orig)
{MyBoxed *a = orig;g_free (a->bla);g_slice_free (MyBoxed, a);my_boxed_free_count++;
}static GType my_boxed_get_type (void);
#define MY_TYPE_BOXED (my_boxed_get_type ())G_DEFINE_BOXED_TYPE (MyBoxed, my_boxed, my_boxed_copy, my_boxed_free)

接下来,我们分析下my_boxed_copy是如何被调用的,首先我们需要先来看看 G_DEFINE_BOXED_TYPE都做了那些事情。

#define G_DEFINE_BOXED_TYPE(TypeName, type_name, copy_func, free_func) G_DEFINE_BOXED_TYPE_WITH_CODE (TypeName, type_name, copy_func, free_func, {})#define G_DEFINE_BOXED_TYPE_WITH_CODE(TypeName, type_name, copy_func, free_func, _C_) _G_DEFINE_BOXED_TYPE_BEGIN (TypeName, type_name, copy_func, free_func) {_C_;} _G_DEFINE_TYPE_EXTENDED_END()#define _G_DEFINE_BOXED_TYPE_BEGIN(TypeName, type_name, copy_func, free_func) \
static GType type_name##_get_type_once (void); \
\
GType \
type_name##_get_type (void) \
{ \static gsize static_g_define_type_id = 0; \......GType g_define_type_id = type_name##_get_type_once ();......static GType \
type_name##_get_type_once (void) \
{ \GType (* _g_register_boxed) \(const gchar *, \union \{ \TypeName * (*do_copy_type) (TypeName *); \TypeName * (*do_const_copy_type) (const TypeName *); \GBoxedCopyFunc do_copy_boxed; \} __attribute__((__transparent_union__)), \union \{ \void (* do_free_type) (TypeName *); \GBoxedFreeFunc do_free_boxed; \} __attribute__((__transparent_union__)) \) = g_boxed_type_register_static; \GType g_define_type_id = \_g_register_boxed (g_intern_static_string (#TypeName), copy_func, free_func); \......
}GType
g_boxed_type_register_static (const gchar   *name,GBoxedCopyFunc boxed_copy,GBoxedFreeFunc boxed_free)
{static const GTypeValueTable vtable = {boxed_proxy_value_init,boxed_proxy_value_free,boxed_proxy_value_copy,boxed_proxy_value_peek_pointer,"p",boxed_proxy_collect_value,"p",boxed_proxy_lcopy_value,};GTypeInfo type_info = {0,			/* class_size */NULL,		/* base_init */NULL,		/* base_finalize */NULL,		/* class_init */NULL,		/* class_finalize */NULL,		/* class_data */0,			/* instance_size */0,			/* n_preallocs */NULL,		/* instance_init */&vtable,		/* value_table */};GType type;g_return_val_if_fail (name != NULL, 0);g_return_val_if_fail (boxed_copy != NULL, 0);g_return_val_if_fail (boxed_free != NULL, 0);g_return_val_if_fail (g_type_from_name (name) == 0, 0);type = g_type_register_static (G_TYPE_BOXED, name, &type_info, 0);/* install proxy functions upon successful registration */if (type)_g_type_boxed_init (type, boxed_copy, boxed_free);return type;
}void
_g_type_boxed_init (GType          type,GBoxedCopyFunc copy_func,GBoxedFreeFunc free_func)
{TypeNode *node = lookup_type_node_I (type);node->data->boxed.copy_func = copy_func;node->data->boxed.free_func = free_func;
}

到此,我们知道my_boxed_copy的存放位置。

Using boxed types

接下来,我们举例说明,在应用程序中,如何使用我们新定义的boxed type的copy函数。

static void
test_define_boxed (void)
{MyBoxed a;MyBoxed *b;a.ivalue = 20;a.bla = g_strdup ("bla");b = g_boxed_copy (MY_TYPE_BOXED, &a);g_assert_cmpint (b->ivalue, ==, 20);g_assert_cmpstr (b->bla, ==, "bla");g_boxed_free (MY_TYPE_BOXED, b);g_free (a.bla);
}

为了搞清楚my_boxed_copy是如何被调用的,我们要分析一下函数g_boxed_copy。

gpointer
g_boxed_copy (GType         boxed_type,gconstpointer src_boxed)
{
......value_table = g_type_value_table_peek (boxed_type);
......if (value_table->value_copy == boxed_proxy_value_copy)dest_boxed = _g_type_boxed_copy (boxed_type, (gpointer) src_boxed);else{
......value_table->value_copy (&src_value, &dest_value);}return dest_boxed;
}gpointer
_g_type_boxed_copy (GType type, gpointer value)
{TypeNode *node = lookup_type_node_I (type);return node->data->boxed.copy_func (value);
}

my_boxed_copy中的if判断,代码应该怎么走呢? 根据g_boxed_type_register_static中的对GTypeInfo的成员value_table的设置,很容易知道,value_table->value_copy == boxed_proxy_value_copy,这个条件是成立的。

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

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

相关文章

ChatTTS源码部署

感谢阅读 默认已完成的操作准备工作下载源码安装依赖下载补丁(报错在运行) 界面展示(discord上有各种补丁&#xff0c;我的加了UI补丁和音色增强)提示词常用&#xff08;这个每个音基本都能生效&#xff09;语调类语速类情感类 默认已完成的操作 python版本>3.9 cuda版本的…

supersocket的app层源码解析

基础结构 #mermaid-svg-Q1MUtx0YWtvpRVNw {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-Q1MUtx0YWtvpRVNw .error-icon{fill:#552222;}#mermaid-svg-Q1MUtx0YWtvpRVNw .error-text{fill:#552222;stroke:#552222;}#…

《化工管理》是什么级别的期刊?是正规期刊吗?能评职称吗?

​问题解答 问&#xff1a;《化工管理》是不是核心期刊&#xff1f; 答&#xff1a;不是&#xff0c;是知网收录的第一批认定学术期刊。 问&#xff1a;《化工管理》级别&#xff1f; 答&#xff1a;国家级。主办单位&#xff1a;中国石油和化学工业联合会 主管单位&…

国产操作系统上配置ssh互信 _ 统信 _ 麒麟 _ 中科方德

原文链接&#xff1a;国产操作系统上配置ssh互信 | 统信 | 麒麟 | 中科方德 Hello&#xff0c;大家好啊&#xff01;今天给大家带来一篇在国产桌面操作系统上配置SSH互信的文章。SSH&#xff08;Secure Shell&#xff09;是一种安全协议&#xff0c;用于在不安全的网络上安全地…

uniapp app分享页面到微信的功能方法

最近开发uniapp app项目时&#xff0c;有分享页面的功能需求&#xff0c;因此&#xff0c;给大家分享一下&#xff0c;在uniapp环境里&#xff0c;是如何分享页面到微信H5页面的。 如上图所示&#xff1a;app主体代码就是这样了&#xff0c;查看相应配置就可以&#xff0c;同时…

Swoole v6 能否让 PHP 再次伟大?

大家好&#xff0c;我是码农先森。 现状 传统的 PHP-FPM 也是多进程模型的的运行方式&#xff0c;但每个进程只能处理完当前请求&#xff0c;才能接收下一个请求。而且对于 PHP 脚本来说&#xff0c;只是接收请求和响应请求&#xff0c;并不参与网络通信。对数据库资源的操作…

图的最短路径算法:原理与实现

图的最短路径算法&#xff1a;原理与实现 在图论中&#xff0c;最短路径算法用于找到图中从一个顶点到另一个顶点的最短路径。常见的最短路径算法包括Dijkstra算法、Bellman-Ford算法和Floyd-Warshall算法。以下是每个算法的详细讲解及其Java实现。 1. Dijkstra算法 原理&am…

Android (已解决)Execution failed for task ‘:app:lint‘

文章目录 一、错误原因二、解决方法 一、错误原因 这个错误信息表示在执行 Lint 检查时发现了错误&#xff0c;导致构建过程被中断。Lint 是一个用于检测 Android 项目中潜在问题的工具&#xff0c;比如性能、安全性、可用性等方面的问题。当Lint检查到严重错误时&#xff0c;…

RabbitMQ如何保证消息可靠

解决办法&#xff1a; 1、做好消息确认机制&#xff08;pulisher、consumer[手动ACK]&#xff09; 2、每一个发送的消息都在数据库做好记录。定期将失败的消息再次发送一遍 消息确认机制&#xff1a; 生产者确认模式&#xff1a;确认消息是否发送到broker&#xff0c;失败…

20240627(26.4) 财经要闻汇总

重点关注 ► 发改委&#xff1a;我国金融规模体系已经很大了&#xff0c;但融资结构还有待改善。耐心资本的培育对于促进我国创业投资高质量发展和实现高水平科技自立自强至关重要。除了充分尊重市场规律以外&#xff0c;政府这只“有形的手”也可以发挥重要作用&#xff0c;引…

【FPGA-常见问题及解决方案】

1、VIVADO的License无法加载&#xff1a;license文件必须在英文路径&#xff1b; 2、例程代码路径不能过长&#xff0c;也不允许有中文路径&#xff01;&#xff01;&#xff01; 3、明明加载了license&#xff0c;license也正确&#xff0c;例程无法完成综合&#xff1a;这种情…

“北京到底有谁在啊”影视APP开发,解锁最简单的快乐

随着电视剧《玫瑰的故事》在腾讯视频APP热播&#xff0c;APP也增加了很多热度&#xff0c;一款丰富的影视APP&#xff0c;无论是热门大片、经典影视剧、还是最新综艺节目&#xff0c;能畅享无限精彩的影视内容&#xff01; 开发影视APP&#xff0c;需要专业的技术服务商来解决…

1500平方米气膜羽毛球馆的造价分析—轻空间

随着全民健身热潮的兴起&#xff0c;气膜羽毛球馆因其良好的空气质量、恒温恒湿的环境和快捷的建设速度&#xff0c;受到了越来越多人的欢迎。建造一个1500平方米的气膜羽毛球馆涉及多个方面的费用&#xff0c;包括场地准备、设备材料、安装施工、配套设施等。轻空间将详细分析…

【设计模式】【结构型7-1】【代理模式】【动态代理】【静态代理】

文章目录 代理模式静态代理第一步 创建接口第二步 创建需要代理的对象第三步 创建代理对象 使用 动态代理jdk动态代理cjlib动态代理 代理模式 代理 是结构型 通过继承&#xff0c;或者实现相同的接口来进行增强和监控 经典的使用 spring aop&#xff0c;mybatis dao层 静态代…

数据清洗的艺术:Python中的Pandas妙用

1. 引言 凡事总须研究&#xff0c;才会明白。在这信息泛滥的时代&#xff0c;数据如同一片混沌的荒原&#xff0c;若不经雕琢&#xff0c;便难以显现其真面目。而对于程序员而言&#xff0c;数据清洗的过程&#xff0c;正是从混沌到秩序的一次次锤炼。 2. 数据清洗的必要性 …

Docker制作Python项目镜像

Docker制作Python项目镜像 背景DockerfileDockerfile内容阐释 制作镜像迁移镜像启动容器 背景 在离线环境部署Python项目&#xff0c;出了需要安装对应版本的Python环境&#xff0c;还需要在项目启动前下载项目所需要的依赖。如果后面的迭代依赖有所更新&#xff0c;在离线环境…

AutoEncoder简介

1.介绍 作为一种无监督或者自监督算法&#xff0c;自编码器本质上是一种数据压缩算法。 编码器&#xff1a; 输入图像&#xff08;在这个例子中是一个28x28像素的数字“9”&#xff09;首先被输入到编码器中。编码器的任务是将这个输入压缩成一个更小的、密集的表示形式&…

docker配置国内镜像加速器

1、搜索阿里云 2、搜索容器镜像服务 点击管理控制台 配置镜像加速器

跌幅高达10.2分!32本Top,Elsevier旗下在检SSCI期刊(2024年6月影响因子更新版)

本周投稿推荐 SSCI • 1区&#xff0c;4.0-5.0&#xff08;无需返修&#xff0c;提交可录&#xff09; EI • 各领域沾边均可&#xff08;2天录用&#xff09; CNKI • 7天录用-检索&#xff08;急录友好&#xff09; SCI&EI • 4区生物医学类&#xff0c;0.1-0.5&…

【AI应用探讨】—朴素贝叶斯应用场景

目录 文本分类 推荐系统 信息检索 生物信息学 金融领域 医疗诊断 其他领域 文本分类 垃圾邮件过滤&#xff1a;朴素贝叶斯被广泛用于垃圾邮件过滤任务&#xff0c;通过邮件中的文本内容来识别是否为垃圾邮件。例如&#xff0c;它可以基于邮件中出现的单词或短语的概率来…