GTK的非实例化类型-interface
来源:互联网 发布:淘宝店铺封店重开技巧 编辑:程序博客网 时间:2024/05/29 13:26
本节将介绍接口背后的理论。 如何定义和实现接口详见 How to define and implement interfaces章节。
例如,下面代码注册一个实现ViewerEditable的新的ViewerFile类:
首先分配一个内存缓冲区来保存接口结构。父级的接口结构然后被复制到新的接口结构中(父接口已经在那时被初始化了)。如果没有父接口,接口结构将使用零初始化。g_type和g_instance_type字段随后被初始化:g_type被设置为最传导接口的类型,并且g_instance_type被设置为实现该接口的最导出类型的类型。
调用接口base_init,然后调用接口的default_init。最后,如果类型已经注册了该接口的实现,则会调用该实现的interface_init函数。如果有一个接口的多个实现,对于初始化的每个实现,base_init和interface_init函数都将被调用一次。因此建议使用default_init函数来初始化一个接口。该函数只会被调用一次,无论这个接口有多少个实现。default_init函数由G_DEFINE_INTERFACE声明,可用于定义接口:
Invocation time Function Invoked Function's parameters Remark First call to 接口销毁
当注册接口的一个可实例化类型的最后一个实例被销毁时,与该类型关联的接口实现被会被销毁。要破坏接口实现,GType首先调用实现的interface_finalize函数,然后再调用接口最传统的base_finalize函数。
同样重要的是要理解,如在“接口初始化”一节中,interface_finalize和base_finalize都被调用一次,以便破坏每个接口的实现。
因此,如果要使用这些函数之一,则需要使用静态整数变量,该变量将保存接口实现的实例数,以使接口的类仅被破坏一次(当整数变量达到零时)。
上述过程可概括如下:
Invocation time Function Invoked Function's parameters Last call to
GType的接口非常类似于Java的接口。 它们允许设计一个通用接口,几个类将遵循这个接口。想象一下,高保真设备上的播放,暂停和停止按钮 - 可以看作播放界面。一旦你知道他们做了什么,你可以控制你的CD播放器,MP3播放器或任何使用这些符号的东西。要声明一个接口,你必须注册一个派生自GTypeInterface的不可实例化的类类型。 以下代码段声明了这样一个接口。
#define VIEWER_TYPE_EDITABLE viewer_editable_get_type ()G_DECLARE_INTERFACE (ViewerEditable, viewer_editable, VIEWER, EDITABLE, GObject)struct _ViewerEditableInterface { GTypeInterface parent; void (*save) (ViewerEditable *self, GError **error);};void viewer_editable_save (ViewerEditable *self, GError **error);viewer_editable_get_type注册一个名为ViewerEditable的类型,它继承自G_TYPE_INTERFACE。 所有接口必须是继承树中G_TYPE_INTERFACE的子节点。一个接口必须由一个包含GTypeInterface结构的作为第一个成员的结构来定义。接口结构期望包含接口方法的函数指针。为每个简单地直接调用接口方法的接口方法定义帮助函数是很好的风格:viewer_editable_save是其中之一。如果没有特殊要求,可以使用G_IMPLEMENT_INTERFACE宏来实现一个接口:
static voidviewer_file_save (ViewerEditable *self){ g_print ("File implementation of editable interface save method.\n");}static voidviewer_file_editable_interface_init (ViewerEditableInterface *iface){ iface->save = viewer_file_save;}G_DEFINE_TYPE_WITH_CODE (ViewerFile, viewer_file, VIEWER_TYPE_FILE, G_IMPLEMENT_INTERFACE (VIEWER_TYPE_EDITABLE, viewer_file_editable_interface_init));如果你的代码有特殊的要求,你必须编写一个自定义的get_type函数来注册你的GType,它继承自一些GObject,并且实现了接口ViewerEditable。
例如,下面代码注册一个实现ViewerEditable的新的ViewerFile类:
static voidviewer_file_save (ViewerEditable *editable){ g_print ("File implementation of editable interface save method.\n");}static voidviewer_file_editable_interface_init (gpointer g_iface, gpointer iface_data){ ViewerEditableInterface *iface = g_iface; iface->save = viewer_file_save;}GType viewer_file_get_type (void){ static GType type = 0; if (type == 0) { const GTypeInfo info = { sizeof (ViewerFileClass), NULL, /* base_init */ NULL, /* base_finalize */ NULL, /* class_init */ NULL, /* class_finalize */ NULL, /* class_data */ sizeof (ViewerFile), 0, /* n_preallocs */ NULL /* instance_init */ }; const GInterfaceInfo editable_info = { (GInterfaceInitFunc) viewer_file_editable_interface_init, /* interface_init */ NULL, /* interface_finalize */ NULL /* interface_data */ }; type = g_type_register_static (VIEWER_TYPE_FILE, "ViewerFile", &info, 0); g_type_add_interface_static (type, VIEWER_TYPE_EDITABLE, &editable_info); } return type;}给定类型实现的类型系统中的g_type_add_interface_static记录也是FooInterface(foo_interface_get_type返回FooInterface的类型)。 GInterfaceInfo结构保存有关接口实现的信息:
struct _GInterfaceInfo{ GInterfaceInitFunc interface_init; GInterfaceFinalizeFunc interface_finalize; gpointer interface_data;};当第一次创建实现接口(直接或通过继承超类的实现)的实例化类时,其类结构将按照“Instantiable classed types: objects”一节中描述的过程进行初始化。之后,与该类型相关联的接口实现被初始化。
首先分配一个内存缓冲区来保存接口结构。父级的接口结构然后被复制到新的接口结构中(父接口已经在那时被初始化了)。如果没有父接口,接口结构将使用零初始化。g_type和g_instance_type字段随后被初始化:g_type被设置为最传导接口的类型,并且g_instance_type被设置为实现该接口的最导出类型的类型。
调用接口base_init,然后调用接口的default_init。最后,如果类型已经注册了该接口的实现,则会调用该实现的interface_init函数。如果有一个接口的多个实现,对于初始化的每个实现,base_init和interface_init函数都将被调用一次。因此建议使用default_init函数来初始化一个接口。该函数只会被调用一次,无论这个接口有多少个实现。default_init函数由G_DEFINE_INTERFACE声明,可用于定义接口:
G_DEFINE_INTERFACE (ViewerEditable, viewer_editable, G_TYPE_OBJECT);static voidviewer_editable_default_init (ViewerEditableInterface *iface){ /* add properties and signals here, will only be called once */}或者您可以自己实现在自己的GType函数中:
viewer_editable_get_type (void){ static volatile gsize type_id = 0; if (g_once_init_enter (&type_id)) { const GTypeInfo info = { sizeof (ViewerEditableInterface), NULL, /* base_init */ NULL, /* base_finalize */ viewer_editable_default_init, /* class_init */ NULL, /* class_finalize */ NULL, /* class_data */ 0, /* instance_size */ 0, /* n_preallocs */ NULL /* instance_init */ }; GType type = g_type_register_static (G_TYPE_INTERFACE, "ViewerEditable", &info, 0); g_once_init_leave (&type_id, type); } return type_id;}static voidviewer_editable_default_init (ViewerEditableInterface *iface){ /* add properties and signals here, will only called once */}
Table 2. Interface Initialization
g_type_create_instance
for any type implementing interfaceinterface's base_init
functionOn interface's vtableRarely necessary to use this. Called once per instantiated classed type implementing the interface.First call to g_type_create_instance
for each type implementing interfaceinterface's default_init
functionOn interface's vtableRegister interface's signals, properties, etc. here. Will be called once.First call to g_type_create_instance
for any type implementing interfaceimplementation's interface_init
functionOn interface's vtableInitialize interface implementation. Called for each class that that implements the interface. Initialize the interface method pointers in the interface structure to the implementing class's implementation.当注册接口的一个可实例化类型的最后一个实例被销毁时,与该类型关联的接口实现被会被销毁。要破坏接口实现,GType首先调用实现的interface_finalize函数,然后再调用接口最传统的base_finalize函数。
同样重要的是要理解,如在“接口初始化”一节中,interface_finalize和base_finalize都被调用一次,以便破坏每个接口的实现。
因此,如果要使用这些函数之一,则需要使用静态整数变量,该变量将保存接口实现的实例数,以使接口的类仅被破坏一次(当整数变量达到零时)。
上述过程可概括如下:
Table 3. Interface Finalization
g_type_free_instance
for type implementing interfaceinterface's interface_finalize
functionOn interface's vtableinterface's base_finalize
functionOn interface's vtable 0 0
- GTK的非实例化类型-interface
- gtk 的第一个实例
- gtk多线程的程序实例
- gtk带glade的实例
- GTK+ 在非GTK主线程 创建新的GTK窗体崩溃问题 解决方案
- Gtk+实现非规则按钮的不同状态图片切换
- Gtk+实现非规则按钮的不同状态图片切换
- JAVA基础的interface与inheritance实例
- java interface的一个经典实例
- GTK+剪贴板使用实例
- [代码实例][gtk+]画布
- 非对称类型的 Comparator
- 非类型的模板参数
- 非静态实例的初始化
- 非静态实例的初始化
- 理解static与非static部分的实例化
- @interface 、类型id
- golang:interface{}类型测试
- 3.1 Linux中的文件IO (3节)
- 逻辑非操作符
- SOAP、WSDL、Web Service详解
- web面试题
- Matlab中plot函数参数解析
- GTK的非实例化类型-interface
- linux 初级学习之文本处理工具2-6
- 抽象工厂模式
- git删除远程文件夹或文件的方法
- js操作符优先级
- Kafka从入门到实践
- 使用Angular4.0开发星级评价组件
- 解析excel+结合表单上的数据生成csv文件
- 百度地图定位