如何定义和实现新的GObject之代码实现
来源:互联网 发布:win10有线网络设置 编辑:程序博客网 时间:2024/06/05 05:00
本章重点介绍了GObject子类的实现,例如创建自定义继承类,或者实现GTK +窗口类的子类。
在整个章节中,使用文件查看器程序的作为示例,其具有用于表示单个文件查看的ViewerFile类,以及具有特殊功能的不同类型的文件(例如音频文件)的各种派生类。 示例应用程序还支持通过使用ViewerEditable接口编辑文件(例如,调整正在查看的照片)。
1、头文件实现
编写GObject代码之前的第一步是编写类型的头文件,其中包含所需的类型,函数和宏定义。 这些元素中的每一个都只是GObject所有用户遵循的约定,并且在多年的开发基于GObject的代码的经验中进行了改进。 如果你正在写一个库,那么遵守这些约定是尤为重要的; 您的用户将会假定你已经遵循这些约定。 即使你不是在写库,遵守这些约定也会帮助其他想要在你的项目上工作的人。
为您的标题和源代码选择一个约定的名称,并坚持下去:
(1)使用破折号将前缀与typename分开:viewer-file.h和viewer-file.c(这是Nautilus和大多数GNOME库使用的约定)。
(2)使用下划线将前缀与typename分开:viewer_file.h和viewer_file.c。
(3)不要将前缀与typename:viewerfile.h和viewerfile.c分开。 (这是GTK +使用的惯例)
有些人喜欢前两种方法:它使阅读文件名更为容易。
任何GType的基本约定在“约定”一节中描述。
如果要在命名空间'viewer'中声明一个名为'file'的类型,请命名实例类型为ViewerFile,类类型命名为ViewerFileClass(名称区分大小写)。 约定的方法是根据类型是基类还是派生类型的不同而不同。
Final types类型不能进一步子类化,并且应该是新类型的默认选择 - 将Final types更改为可继承的类型始终是与现有代码使用兼容的更改,但相反的往往会导致问题。 Final types使用G_DECLARE_FINAL_TYPE声明,并且要求在源代码(而不是头文件)中声明的实例结构体。
/* * Copyright/Licensing information. *//* inclusion guard */#ifndef __VIEWER_FILE_H__#define __VIEWER_FILE_H__#include <glib-object.h>/* * Potentially, include other headers on which this header depends. */G_BEGIN_DECLS/* * Type declaration. */#define VIEWER_TYPE_FILE viewer_file_get_type ()G_DECLARE_FINAL_TYPE (ViewerFile, viewer_file, VIEWER, FILE, GObject)/* * Method definitions. */ViewerFile *viewer_file_new (void);G_END_DECLS#endif /* __VIEWER_FILE_H__ */继承类可以被子类化,其类和实例结构构成公共API的一部分,如果API稳定性关注,则不能更改。 它们使用G_DECLARE_DERIVABLE_TYPE声明:
/* * Copyright/Licensing information. *//* inclusion guard */#ifndef __VIEWER_FILE_H__#define __VIEWER_FILE_H__#include <glib-object.h>/* * Potentially, include other headers on which this header depends. */G_BEGIN_DECLS/* * Type declaration. */#define VIEWER_TYPE_FILE viewer_file_get_type ()G_DECLARE_DERIVABLE_TYPE (ViewerFile, viewer_file, VIEWER, FILE, GObject)struct _ViewerFileClass{ GObjectClass parent_class; /* Class virtual function fields. */ void (* open) (ViewerFile *file, GError **error); /* Padding to allow adding up to 12 new virtual functions without * breaking ABI. */ gpointer padding[12];};/* * Method definitions. */ViewerFile *viewer_file_new (void);G_END_DECLS#endif /* __VIEWER_FILE_H__ */头文件的约定是将最少的头文件#include到需要编译该头文件的顶部。 这允许客户端代码简单地#include“viewer-file.h”,而不需要知道viewer-file.h的先决条件。
2、源代码实现
在源码里面第一步应该先#include需要的头文件
/* * Copyright information */#include "viewer-file.h"/* Private structure definition. */typedef struct { gchar *filename; /* stuff */} ViewerFilePrivate;/* * forward definitions */如果这个类使用G_DECLARE_FINAL_TYPE声明为不可继承的final types,那么他的实例结构体应当定义在.c文件中。
struct _ViewerFile{ GObject parent_instance; /* Other members, including private data. */}
调用G_DEFINE_TYPE宏(或G_DEFINE_TYPE_WITH_PRIVATE如果您的类需要私有数据 - final types不需要私有数据),使用类型名称,函数前缀和父类GType来减少所需的代码数量。这个宏将做如下操作:
(1)实现viewer_file_get_type函数
(2)定义可以从整个.c文件访问的父类指针
(3)将私有实例数据添加到该类型(如果使用G_DEFINE_TYPE_WITH_PRIVATE)
如果使用G_DECLARE_FINAL_TYPE(参见“Boilerplate头代码”一节)将类声明为final,那么私有数据应该放在实例结构中,应该使用ViewerFile和G_DEFINE_TYPE替代G_DEFINE_TYPE_WITH_PRIVATE。final类型的实例结构不会公开暴露,也不会嵌入到任何派生类的实例结构中(因为该类是final);所以它的大小可以变化,而不会导致使用该类的代码不兼容。相反,可继承类的私有数据必须包含在私有结构中,必须使用G_DEFINE_TYPE_WITH_PRIVATE。
G_DEFINE_TYPE(ViewerFile, viewer_file, G_TYPE_OBJECT)
或者
G_DEFINE_TYPE_WITH_PRIVATE(ViewerFile, viewer_file, G_TYPE_OBJECT)
也可以使用G_DEFINE_TYPE_WITH_CODE宏来控制get_type函数实现-例如,添加一个调用G_IMPLEMENT_INTERFACE宏来实现一个接口。
- 如何定义和实现新的GObject之代码实现
- 如何定义和实现新的GObject之对象方法
- 如何定义和实现新的GObject之对象构造和析构
- GObject接口定义和实现
- GObject 参考手册:教程:如何定义和实现接口
- 定义、注册和实现 GObject 类的子类
- GObject:用C实现类是如何做到的
- GObject接口定义的先决条件和属性
- GObject-GSignal实现
- Gobject编程实现
- GObject Tutorial 和GObject手册的中文版
- 协议的定义和实现
- 【复数】的定义和实现
- 【有理数】的定义和实现
- 栈的定义和实现
- 堆栈的定义和实现
- 数据结构学习之-二叉树的定义和存储实现
- quagga 命令定义的代码分析--从定义到实现
- c#,winform实现获取当前经纬度坐标(极其便捷)
- Spring必须掌握的技术
- Linux下查找输出文本中特定的内容
- finally 语句块的深度辨析
- 二叉树的递归和非递归
- 如何定义和实现新的GObject之代码实现
- 制作pe的U盘在BIOS启动选择菜单显示两个UEFI项的浅析
- 关于2sdcard的内外切换
- Xamarin XAML语言教程Xamarin.Forms中构建进度条
- docx4j 处理word2007文档
- 【初探】选择排序 学习笔记
- django--创建网站小样
- 008-dockerbook中的命令总结(2)
- Problem C: 选举班干部了!