Как применять типы в Gtk+


   
 

Версия: 0.1 Aвтор: Андрей Ржавсков (Andrey Rjavskov [Rzhavskov]) as known rjaan


   
 

1.Введение

 
 

Разработка графичесrких программ в Gtk+ ведется в объектно-ореентированной среде, которая базируется на объектной системы GLib (библиотека gobject) для языка Си (далее по тексту — С/GObject). Её не следует путать с библиотекой GLIB, предоставляющей функциональный набор для работы с фундаментальными типами и алгоритмами в Gtk+, такими как списки, хэши и т.д.

В статье Как создать главное окно программы в Gtk+ создавался пользовательский (статический) тип UGtkMainWindow с использованием интерфейса прикладного программирования GType (далее — API GType), на котором строится вся работа с типами в С/GObject. По сути API GType является окружением С/GObject в части индентификации типов и их управления.

   
 

2. Идентификация и управление типами в С/GObject

 
 

2.1. Статические и фундаментальные типы

 
 

Как древние люди представляли себе, что земля держится на китах, так и С/GObject основывается на API GType, которые обеспечивают регистрацию и манипулирование типами данных, определенных пользователем объектов и интерфейсных типов.

В настоящее время, API GType позволяют программисту создавать и манипулировать двумя видами типов — статическими и фундаментальными. Остальные виды типизации, используемой в С/GObject являются лишь ветлением данных двух типов.

#include <gobject/gtype.h>
typedef struct _GTypeInfo     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; /* количество созданных экземпляров c
выделением памяти (оператор new() в С++ ) */
GInstanceInitFunc    instance_init; /* Инциализация экземпляра*/
 
/*Таблица функций, встроенных обработчиков GValues */
const GTypeValueTable  *value_table;
};
 
/* регистрация статического типа */
GType g_type_register_static ( GType parent_type, /* Родительский тип */
const gchar *type_name, /* текстовое имя типа */
const GTypeInfo *info, /* GTypeInfo */
GTypeFlags flags); /* Флаги */
 
/* регистрация фундаментального типа */
GType g_type_register_fundamental (GType type_id,
const gchar *type_name,
const GTypeInfo *info,
const GTypeFundamentalInfo *finfo,
GTypeFlags flags);

Соответственно, во время выполнение программы, для динамической регистрации в С/GObject нового статического типа следует использовать g_type_register_static(), а фундаментального типа — g_type_register_fundamental(). Обе функции создают новый GType на основе предаставленной информации о создаваемом типе в GTypeInfo. Как бы не казались оба типа с виду одинаковами, но они имеют существенное различие.

Так в статье Как создать главное окно программы в Gtk+ мы регистрировали в С/GObject статический тип UGtkMainWindow, потому что нам нужно было наследовать свойства такого же статического типа GtkWindow. В тоже время при регистрации фундаментального типа такая возможность отсутствует, так данный тип относится к так называемому типу ТОП-уровня и не может быть производным от кого-либо другого типа.

Сама регистрация статических и фундаметальных типов так же различается и довольно существенно, как видно из ниже приведенного фрагмента кода из регистрации статического типа UGtkMainWindow.

Файл libugtk-widgets/ugtkmainwindow.c

 . . .
 
/* Функция создания статистического типа UGtkMainwindow */
 
GType ugtk_mainwindow_get_type (void)
{
static GType g_type = 0;
 
if (!g_type) {
static const GTypeInfo type_info =
{
sizeof (UGtkMainwindowClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) ugtk_mainwindow_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (UGtkMainwindow),
0,
(GInstanceInitFunc) ugtk_mainwindow_init,
};
 
g_type = g_type_register_static ( GTK_TYPE_WINDOW,
"UGtkMainwindow", &type_info, 0 );
}
 
return g_type;
}
 
 . . .

Как видно из текста кода в GTypeInfo нужно предоставить следующую информацию:

  • в поле class_size — сведения о размере структурного типа класса объекта;
  • в поле class_init — функцию, инициализирующая данный структурный тип класса объекта;
  • в поле instance_size — сведения о размере структурного типа экземпляра класса объекта с обнулением количества созданных в памяти экземпляров объектов в поле n_preallocs;
  • в поле instance_init — функцию, инициализирующую структурный экземпляр данного типа класса объекта;

Остальные поля GTypeInfo, такие как base_init, base_finalize и class_finalize при регистрации типа UGtkMainWindow обычно не задействуются явно и обнуляются с использованием NULL-указателей.

При регистрации фундаментальных типов по-мимо GTypeInfo, отвечающей за манипуляции с создаваемым фундаментальным типом, ещё используется GTypeFundamentalInfo для определение поведения создаваемого типа.

Как можно заметить в GTypeInfo используются на первый взгляд нетрадиционные для Си типы данных, но это не так. Квалификаторы типов полей GTypeInfo на самом деле являются идентификаторами фундаментальных и базовых типов Си, представляющие собой в С/GOBJECT набор базовых типов Си и призванные облегчить программисту жизнь при их использовании и дальнейшей портируемости.

   
 

2.2. Набор базовых типов в С/GOBJECT

 
 

В качестве базового набора типов в С/GOBJECT используются идентификаторы фундаментальных и производных типов Си, образованных спецификатором typedef. Более подробную информацию о работе с фундаментальными и производными типами в Си можно почерпнуть в статье Основные операции с типами данных в С/С++.

Язык программирования Си оперирует следующими фундаментальными типами:

  • символьные — char;
  • целые — short, int, long;
  • типы с плавающей точкой одинарной точности float и двойной double;
  • Типы перечисления (или перечесляемый тип) наподобие enum;
  • Тип отсутствия информации void.

В C/GObect главным образом используются идентификаторы типов, которые можно разделить на четыре группы:

  • идентификаторы типов gboolean, gsize, gssize, goffset, gintptr, guintptr, которые были образованны от типов, непредусмотренных стандартом языка программирования Си (но, определяемые другими его вариациями, в т.ч. в заголовочных файлах различных бибилотек);
  • идентификаторы типов gint8, guint8, gint16, guint16, gint32, guint32, gint64, guint64, образованных от интегральных типов, которым гарантированно соответствие одному и тому же размеру на всех известных платформах.
  • идентификаторы типов guchar, guint, gushort, gulong, призванных облегчить жизнь программисту и определяемые в Си с использованием квалификатора signed/unsigned; так же в эту группу входят идентификаторы типов такие как gpointer и gconstpointer, образованные от производных типов, но явно отсутствующий в Си.
  • идентификаторы типов gchar, gint, gshort, glong, gfloat, gdouble, образованные от фундаментальных типов в языке Си.

В С/GObject определены макросы для лимитирование значений стандартных интегральных типов и типов с плавающей точкой, которые перечислены ниже, в следующей таблице.

Наименование типа Си Идентификатор типа С/GOBJECT Максимальное значение Минимальное значение
Логический тип (образован от gint) gboolean TRUE(значение обратное FALSE) FALSE(значение 0)
Указатель типа void* gpointer Не используется
Указатель типа void* на неизменяемые данные gconstpointer Не используется
Символьный тип с учетом знака gchar G_MAXINT8 G_MININT8
Символьный тип без учета знака guchar G_MAXUINT8 G_MINUINT8
Целочисленный тип int c учетом знака gint G_MAXINT G_MININT
Целочисленный тип int без учета знака guint G_MAXUINT G_MINUINT
Короткий целочисленный тип short c учетом знака gshort G_MAXSHORT G_MINSHORT
Короткий целочисленный тип short без учета знака gushort G_MAXUSHORT G_MINUSHORT
Длинный целочисленный тип long c учетом знака glong G_MAXLONG G_MINLONG
Длинный целочисленный тип long без учета знака gulong G_MAXULONG G_MINULONG
Целочисленный тип размерность 8 разрядов c учетом знака gint8 G_MAXINT8 G_MININT8
Целочисленный тип размерностью 8 разрядов без учета знака guint8 G_MAXUINT8 G_MINUINT8
Целочисленный тип размерностью 16 разрядов c учетом знака gint16 G_MAXINT16 G_MININT16
Целочисленный тип размерностью 16 разрядов без учета знака guint16 G_MAXUINT16 G_MINUINT16
Целочисленный тип размерностью 32 разряда c учетом знака gint32 G_MAXINT32 G_MININT32
Целочисленный тип размерностью 32 разряда без учета знака guint32 G_MAXUINT32 G_MINUINT32
Целочисленный тип размерностью 64 разряда c учетом знака gint64 G_MAXINT64 G_MININT64
Целочисленный тип размерностью 64 разряда без учета знака guint64 G_MAXUINT64 G_MINUINT64
Тип с плавающей точкой одинарной точности float gfloat G_MAXFLOAT G_MINFLOAT
Тип с плавающей точкой двойной точности double gdouble G_MAXDOUBLE G_MINDOUBLE
Размерность данных в байтах (определена в С99 как тип size_t) gsize G_MAXSIZE 0UL
Размерность данных в байтах c учетом знака ( в некторых стандартах определена как тип ssize_t) gssize G_MAXSSIZE G_MINSSIZE
Целочесленный тип с учетом знака, используемый при операция смещения внутри файла и области данных ( определен в С99 как тип off64_t) goffset G_MAXOFFSET G_MINOFFSET
Длинный целочисленный тип с учетом знака, содержащий адрес указателя ( определен в С99 как тип intptr_t) gintptr G_MAXLONG G_MINLONG
Длинный целочисленный тип без учета знака, содержащий адрес указателя ( определен в С99 как тип uintptr_t) guintptr G_MAXULONG G_MINULONG

Для типов gulong, glong, gsize, gssize, goffset, gintptr и guintptr размерность изменяется в зависимости от того какая разрядность имеет ваша система, так на 32 разрядной системе перечисленные типы будут иметь 32 разряда, а на 64-х разрядной соответственно 64. Остальные типы всегда будут иметь размер не более 32-х разрядов в силу своей малой размерности.

Все выше перечисленные макросы минимальной и максимальной размерности типов обычно используются для проверки соблюдения размера данных в операциях приводящих к переполнению типа или при работе с массивами данных во-избежание выхода за их границы.

   
 

4. Библиография

 
 

4.1. GObject Reference Manual
4.2. The GLib Dynamic Type System
4.3. Basic Types
4.4. Как создать главное окно программы в Gtk
4.5. Основные операции с типами данных в С/С++

   
   
Вернуться к Оглавлению

 Copyright © 2010-2014 rjaan as Andrey Rjavskov(Rzhavskov) <rjaan@yandex.ru> <arjavskov@gmail.com>
 
Сайт создан в системе uCoz