惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Cloudbric
Cloudbric
E
Exploit-DB.com RSS Feed
SecWiki News
SecWiki News
Forbes - Security
Forbes - Security
N
News | PayPal Newsroom
S
Security @ Cisco Blogs
Schneier on Security
Schneier on Security
V
V2EX - 技术
S
Secure Thoughts
W
WeLiveSecurity
Google DeepMind News
Google DeepMind News
C
CERT Recently Published Vulnerability Notes
NISL@THU
NISL@THU
S
Securelist
S
Security Archives - TechRepublic
Know Your Adversary
Know Your Adversary
V
Vulnerabilities – Threatpost
Security Latest
Security Latest
Recent Commits to openclaw:main
Recent Commits to openclaw:main
G
GRAHAM CLULEY
H
Hacker News: Front Page
Microsoft Azure Blog
Microsoft Azure Blog
I
Intezer
Google Online Security Blog
Google Online Security Blog
美团技术团队
阮一峰的网络日志
阮一峰的网络日志
T
The Exploit Database - CXSecurity.com
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Webroot Blog
Webroot Blog
Jina AI
Jina AI
Engineering at Meta
Engineering at Meta
P
Proofpoint News Feed
The Cloudflare Blog
I
InfoQ
L
LangChain Blog
U
Unit 42
P
Proofpoint News Feed
S
Schneier on Security
S
Security Affairs
Y
Y Combinator Blog
T
Tenable Blog
N
News and Events Feed by Topic
MyScale Blog
MyScale Blog
量子位
Google DeepMind News
Google DeepMind News
Cyberwarzone
Cyberwarzone
博客园 - 聂微东
D
Darknet – Hacking Tools, Hacker News & Cyber Security
GbyAI
GbyAI
AWS News Blog
AWS News Blog

博客园 - 高原

[转] GType 类型系统的功能 [转] Android FrameWork——Touch事件派发过程详解 [转] GObject对象系统 [转] GTYPE类型系统分析 VC里嵌汇编,获取寄存器的值 [转] 使用dbghelp获取调用堆栈--release下的调试方法学 [转] 探索Win32系统之窗口类(Window Classes in Win32) [转] 编译器开关参数集 [转] Nano-X的详细介绍 [转] 为MicroWindows添加透明绘图函数 [转] microwindows位图解析 [转] Microwindows及其中文化方法 [转] Nano-X显示系统的代码分析 [转] Nano-X图形引擎分析及其优化 [转] 使用 pq magic 分区出现 Error 983 报错信息的处理办法 [转] IncrediBuild 试用时间推迟的算法 [原创] MicroWindows学习笔记之底层消息的读取 [原创] MicroWindows学习笔记之对底层设备的管理 [转载] Makefile详解
[转] 定义、注册和实现 GObject 类的子类
高原 · 2012-06-24 · via 博客园 - 高原

定义 GObject 的子类

·    instance 结构:包含于类的实例相关的域,相当于 C++ 中的非静态公共成员。

·    class 结构:包含的域相当于 C++ 中的静态公共成员。

·    私有成员在哪里定义?

C++ 不同,私有成员不是直接定义在类的声明中的(你甚至找不到一个到私有数据的指针)。GObject 的私有数据是在 class 结构初始化的时候,通过调用 g_typ_class_add_private 函数来指定的,这个函数只是指定私有数据的大小,类型系统在分配 instance 的时候会预留指定大小的空间供类实现作为私有数据使用。

·    例子代码及注释(代码来自"Foundations of Gtk+ Development"一书第十一章)

#include <glib.h>

#include <glib-object.h>

#include <gtk/gtkentry.h>  

G_BEGIN_DECLS  

#define MY_IP_ADDRESS_TYPE (my_ip_address_get_type ())

#define MY_IP_ADDRESS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MY_IP_ADDRESS_TYPE, MyIPAddress))

#define MY_IP_ADDRESS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MY_IP_ADDRESS_TYPE, MyIPAddressClass))

#define IS_MY_IP_ADDRESS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MY_IP_ADDRESS_TYPE))

#define IS_MY_IP_ADDRESS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MY_IP_ADDRESS_TYPE))  

typedef struct _MyIPAddress MyIPAddress;

typedef struct _MyIPAddressClass MyIPAddressClass;  

struct _MyIPAddress

{

GtkEntry entry;

};  

struct _MyIPAddressClass

{

GtkEntryClass parent_class;  

void (* ip_changed) (MyIPAddress *ipaddress);

};  

GType my_ip_address_get_type (void) G_GNUC_CONST;

GtkWidget* my_ip_address_new (void);  

gchar* my_ip_address_get_address (MyIPAddress *ipaddress);

void my_ip_address_set_address (MyIPAddress *ipaddress, gint address[4]);  

G_END_DECLS

注册 GObject 的子类

·    GObject 类型在使用之前必须在 GType 类型系统中注册,类型的注册工作在 xxx_get_type 函数中完成,例如上面例子中的 my_ip_address_get_type 函数。正如上面的例子所示,这个函数会在 new 一个该类的对象时被调用,如果该类型还没有被注册,则在第一次 new 这个类型的对象时注册。

GType my_ip_address_get_type (void)

{

static GType entry_type = 0;  

if (!entry_type)

{

static const GTypeInfo entry_info = {

sizeof (MyIPAddressClass), NULL, NULL, (GClassInitFunc) my_ip_address_class_init,

NULL, NULL, sizeof (MyIPAddress), 0, (GInstanceInitFunc) my_ip_address_init,

};  

entry_type = g_type_register_static (GTK_TYPE_ENTRY, "MyIPAddress", &entry_info, 0);

}  

return entry_type;

}

不过上面的代码不是线程安全的。在 gtype.h 中(只要包含了 glib-object.h 就会自动包含这个文件)定义了一个方便的宏,它是线程安全的。这个宏是 #define G_DEFINE_TYPE(TN, t_n, T_P),不过它的实现只使用了 g_type_register_static_simple 函数(见下面),不够灵活,如果需要自己完整定义 GTypeInfo 结构的话,可以参考这个宏的实现。

·    通过 GType API 在类型系统中注册一个类:

GType g_type_register_static (GType parent_type, const gchar *type_name, const GTypeInfo *info, GTypeFlags flags);

GType g_type_register_static_simple (GType parent_type, const gchar *type_name, guint class_size, GClassInitFunc class_init, guint instance_size, GInstanceInitFunc instance_init, GTypeFlags flags);

·    类型的大部分信息保存在 GTypeInfo 数据结构中,

struct _GTypeInfo

{

guint16 class_size;  

GBaseInitFunc base_init;

GBaseFinalizeFunc base_finalize;  

GClassInitFunc class_init;

GClassFinalizeFunc class_finalize;

gconstpointer class_data;  

guint16 instance_size;

guint16 n_preallocs;

GInstanceInitFunc instance_init;  

const GTypeValueTable *value_table;

};

实现 GObject 的子类

实现子类的过程其实就是实现 GTypeInfo 结构中各个函数指针以及该类的接口函数的过程,因此首先需要了解 GTypeInfo 各个域的作用,在GObject 类的实现以及对象属性中还会进一步介绍这些函数被调用的顺序。

·    GObject 子类的 GTypeInfo 各个函数的作用

o  base_init:对 class 结构中继承过来的域进行设置。由于继承的域都是直接拷贝父类的 class 结构的,所以有些域可能需要进行深拷贝,这些操作就在这个函数完成。需要注意的是,假如 B 继承 A,是将 B class 结构指针传给 A 所定义的 base_init 函数,因为只有 A 自身知道如何恰当设置相关的域。

o  base_finalize:与 base_init 相反。

o  class_init:这个函数对每个类只会调用一次,class 结构对每个类来说也只有一个副本。这个函数有两个作用,一是对 class 结构中的域进行初始化,二是注册该类的属性、信号、私有数据。

o  class_finalize:与 class_init 相反。

o  instance_init:初始化实例对象。

·    例子代码及注释

static void my_ip_address_class_init (MyIPAddressClass *klass)

{

GObjectClass *gobject_class = G_OBJECT_CLASS (klass);  

gobject_class->set_property = my_ip_address_set_property;

gobject_class->get_property = my_ip_address_get_property;  

g_type_class_add_private (klass, sizeof (MyIPAddressPrivate));  

my_ip_address_signals[CHANGED_SIGNAL] = g_signal_new ("ip-changed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (MyIPAddressClass, ip_changed), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);  

g_object_class_install_property (gobject_class, PROP_IP1, g_param_spec_int ("ip-number-1", "IP Address Number 1", "The first IP address number", 0, 255, 0, G_PARAM_READWRITE));  

g_object_class_install_property (gobject_class, PROP_IP2, g_param_spec_int ("ip-number-2", "IP Address Number 2", "The second IP address number", 0, 255, 0, G_PARAM_READWRITE));  

g_object_class_install_property (gobject_class, PROP_IP3, g_param_spec_int ("ip-number-3", "IP Address Number 3", "The third IP address number", 0, 255, 0, G_PARAM_READWRITE));  

g_object_class_install_property (gobject_class, PROP_IP4, g_param_spec_int ("ip-number-4", "IP Address Number 1", "The fourth IP address number", 0, 255, 0, G_PARAM_READWRITE));

}  

static void my_ip_address_init (MyIPAddress *ipaddress)

{

MyIPAddressPrivate *priv = MY_IP_ADDRESS_GET_PRIVATE (ipaddress);

PangoFontDescription *fd;

guint i;  

for (i = 0; i < 4; i++) priv->address[i] = 0;  

fd = pango_font_description_from_string ("Monospace");

gtk_widget_modify_font (GTK_WIDGET (ipaddress), fd);

my_ip_address_render (ipaddress);

pango_font_description_free (fd);  

g_signal_connect (G_OBJECT (ipaddress), "key-press-event", G_CALLBACK (my_ip_address_key_pressed), NULL);

g_signal_connect (G_OBJECT (ipaddress), "notify::cursor-position", G_CALLBACK (my_ip_address_move_cursor), NULL);

}

转自:http://blog.sina.com.cn/s/blog_69c435f90100mh6z.html