| |
Справочное описание GObject |
---|
Тип, которым манипулирует система типов Glib, намного более общий, чем тот который обычно подразумевается как объектный тип (Object type). Это лучше всего демонстрирует ниже показанная структура и функции используемые для регистрации типа в системе типов.
typedef struct _GTypeInfo GTypeInfo; struct _GTypeInfo { /* interface types, classed types, instantiated types */ guint16 class_size; GBaseInitFunc base_init; GBaseFinalizeFunc base_finalize; /* classed types, instantiated types */ GClassInitFunc class_init; GClassFinalizeFunc class_finalize; gconstpointer class_data; /* instantiated types */ guint16 instance_size; guint16 n_preallocs; GInstanceInitFunc instance_init; /* value handling */ const GTypeValueTable *value_table; }; GType g_type_register_static (GType parent_type, const gchar *type_name, const GTypeInfo *info, GTypeFlags flags); GType g_type_register_fundamental (GType type_id, const gchar *type_name, const GTypeInfo *info, const GTypeFundamentalInfo *finfo, GTypeFlags flags);
g_type_register_static
и
g_type_register_fundamental
являются C функциями, определёнными в gtype.h
и реализованными в gtype.c
которые вы должны использовать для регистрации новых GType
в программной системе типов.
Маловероятно что вам потребуется использовать
g_type_register_fundamental
(вы должны бить Tim Janik, чтобы делать это) но если вам это нужно, последний раздел разъясняет как создаются новые
базовые типы данных.
[2]
Базовые типы данных являются высшим уровнем типов которые не происходят от других типов
в то время как обычные типы происходят из других типов.
После инициализации g_type_init
,
система типов не только инициализирует внутренние сструктуры данных, но и регистрирует множество основных типов:
некоторые из них являются базовыми типами данных. Остальные являются типами полученными из этих базовых типов.
Базовые и небазовые типы данных определяют:
размер класса: поле class_size в GTypeInfo.
функции инициализации класса (C++ конструктор): поля base_init и class_init в GTypeInfo.
функции уничтожения класса (C++ деструктор): поля base_finalize и class_finalize в GTypeInfo.
размер экземпляра (C++ параметр нового): поле instance_size в GTypeInfo.
instanciation policy (C++ тип нового оператора): поле n_preallocs в GTypeInfo.
функции копирования (C++ операторы копирования): поле value_table в GTypeInfo.
флаги характеризующие тип: GTypeFlags.
Базовые типы данных определяются так же набором
GTypeFundamentalFlags
которые хранятся в GTypeFundamentalInfo.
Небазовые типы кроме всего прочего определяются их родителем, который помещается как параметр parent_type в
g_type_register_static
и g_type_register_dynamic
.
Основным обобщением между всеми glib типами (базовыми и небазовыми, классофицированными и неклассофицированными, instantiable и non-instantiable) является то, что ими можно манипулировать через единственный API для копирования и создания типов.
Структура GValue используется как абстрактный контейнер
для всех этих типов. Её упрощенный API (определён в gobject/gvalue.h
) может использоваться для
вызова value_table функций в течение регистрации типа: например
g_value_copy
для копирования содержимого
GValue в другой
GValue. Это подобно назначению в C++,
когда вызывается оператор копирования C++, чтобы по умолчанию побитно модифицировать копию семантики C++/C структур/классов.
Следующий код демонстрирует как можно копировать 64 битное целочисленное,
так же как экземпляр указателя GObject
(код этого примера находится в исходном пакете этой документации в sample/gtype/test.c
):
static void test_int (void) { GValue a_value = {0, }; GValue b_value = {0, }; guint64 a, b; a = 0xdeadbeaf; g_value_init (&a_value, G_TYPE_UINT64); g_value_set_uint64 (&a_value, a); g_value_init (&b_value, G_TYPE_UINT64); g_value_copy (&a_value, &b_value); b = g_value_get_uint64 (&b_value); if (a == b) { g_print ("Yay !! 10 lines of code to copy around a uint64.\n"); } else { g_print ("Are you sure this is not a Z80 ?\n"); } } static void test_object (void) { GObject *obj; GValue obj_vala = {0, }; GValue obj_valb = {0, }; obj = g_object_new (MAMAN_BAR_TYPE, NULL); g_value_init (&obj_vala, MAMAN_BAR_TYPE); g_value_set_object (&obj_vala, obj); g_value_init (&obj_valb, G_TYPE_OBJECT); /* g_value_copy's semantics for G_TYPE_OBJECT types is to copy the reference. This function thus calls g_object_ref. It is interesting to note that the assignment works here because MAMAN_BAR_TYPE is a G_TYPE_OBJECT. */ g_value_copy (&obj_vala, &obj_valb); g_object_unref (G_OBJECT (obj)); g_object_unref (G_OBJECT (obj)); }
Важно в выше представленном коде то, что точная семантика вызова копирования не определена так как зависит от реализации функции копирования. Определённые функции копирования могут решить распределить новый участок памяти и зтем скопировать данные из источника в адресат. Другие могут просто увеличить количество ссылок на экземпляр и скопировать ссылку в новый GValue.
value_table определённый в gtype.h
используется
для определения этих функций и полностью описан в документации API поставляемой с
GObject (for once ;-) это объясняет почему мы не будем детализировать точную семантику.
typedef struct _GTypeValueTable GTypeValueTable; struct _GTypeValueTable { void (*value_init) (GValue *value); void (*value_free) (GValue *value); void (*value_copy) (const GValue *src_value, GValue *dest_value); /* varargs functionality (optional) */ gpointer (*value_peek_pointer) (const GValue *value); gchar *collect_format; gchar* (*collect_value) (GValue *value, guint n_collect_values, GTypeCValue *collect_values, guint collect_flags); gchar *lcopy_format; gchar* (*lcopy_value) (const GValue *value, guint n_collect_values, GTypeCValue *collect_values, guint collect_flags); };
Маловероятно что вы будете когда либо определять value_table в процессе регистрации типа потому что value_tables наследуется из родительского типа для небазовых типов, это значит что если вы хотите создать базовый тип (не очень хорошая идея!), вам не потребуется обеспечить новый value_table так как вы унаследуете структуру value_table из родителя вашего типа.
[2]
Пожалуйста помните что есть другие функции регистрации:
g_type_register_dynamic
.
Мы не будем обсуждать эту функцию здесь, так как её использование очень похоже на версию _static
.
Закладки на сайте Проследить за страницей |
Created 1996-2024 by Maxim Chirkov Добавить, Поддержать, Вебмастеру |