GОбъект
Разработчик(и) | Проект GNOME |
---|---|
Первоначальный выпуск | 11 марта 2002 г |
Написано в | С |
Операционная система | Кросс-платформенный |
Доступно в | Многоязычный [ который? ] |
Тип | Библиотека программного обеспечения |
Лицензия | ГНУ ЛГПЛ |
Веб-сайт | разработчик |
Объектная система GLib , или GObject , — это свободного библиотека программного обеспечения , обеспечивающая переносимую объектную систему и прозрачную межъязыковую совместимость. GObject предназначен для использования как непосредственно в программах на C для предоставления объектно-ориентированных API на основе C, так и через привязки к другим языкам для обеспечения прозрачного межъязыкового взаимодействия, например PyGObject .
История
[ редактировать ]В зависимости только от GLib и libc GObject является краеугольным камнем GNOME и используется в GTK , Pango , ATK и большинстве GNOME библиотек более высокого уровня, таких как GStreamer и приложения. До GTK+ 2.0 код, похожий на GObject, был частью кодовой базы GTK. (Имя «GObject» еще не использовалось — общий базовый класс назывался GtkObject
.)
В выпуске GTK+ 2.0 объектная система была выделена в отдельную библиотеку из-за ее общей полезности. При этом большинство с графическим интерфейсом, частей, не связанных GtkObject
класс был переведен в GObject
, новый общий базовый класс. Существуя как отдельная библиотека с 11 марта 2002 г. (дата выпуска GTK+ 2.0), библиотека GObject теперь используется многими программами без графического интерфейса, такими как приложения командной строки и серверные приложения.
Связь с GLib
[ редактировать ]Хотя GObject имеет свой отдельный набор документации. [ 1 ] и обычно компилируется в отдельный файл общей библиотеки , исходный код GObject находится в дереве исходного кода GLib и распространяется вместе с GLib. По этой причине GObject использует номера версий GLib и обычно упаковывается вместе с GLib (например, Debian помещает GObject в свой пакет). libglib2.0
семейство пакетов).
Система типов
[ редактировать ]На самом базовом уровне инфраструктуры GObject лежит универсальная и динамическая система типов, называемая GType. Система GType содержит описание всех объектов во время выполнения, что позволяет связующему коду облегчить привязку нескольких языков. Система типов может обрабатывать любую структуру классов, унаследованную отдельно , в дополнение к неклассифицированным типам, таким как непрозрачные указатели , строки различного размера , а также целые числа и числа с плавающей запятой .
Система типов умеет копировать, присваивать и уничтожать значения, принадлежащие любому из зарегистрированных типов. Это тривиально для таких типов, как целые числа, но многие сложные объекты имеют подсчет ссылок , а некоторые являются сложными, но без подсчета ссылок. Когда система типов «копирует» объект с подсчетом ссылок, она обычно просто увеличивает его счетчик ссылок, тогда как при копировании сложного объекта без подсчета ссылок (например, строки) она обычно создает фактическую копию, выделяя память .
Эта базовая функциональность используется для реализации GValue
, тип универсального контейнера, который может хранить значения любого типа, известного в системе типов. Такие контейнеры особенно полезны при взаимодействии с динамически типизированными языковыми средами, в которых все собственные значения находятся в таких контейнерах с тегами типа .
Основные типы
[ редактировать ]Типы, не имеющие связанных классов, называются неклассифицированными . Эти типы вместе со всеми типами, которые соответствуют той или иной форме корневого класса , известны как фундаментальные типы : типы, от которых произошли все остальные типы. Они составляют относительно закрытый набор, но, хотя среднестатистический пользователь не должен создавать свои собственные фундаментальные типы, возможность существует и используется для создания пользовательских иерархий классов , т. е. иерархий классов, не основанных на GObject
сорт.
Начиная с GLib 2.9.2, [ 2 ] неклассифицированные : встроенные фундаментальные типы
- пустой тип, соответствующий C
void
(G_TYPE_NONE
); - типы, соответствующие знаковым и беззнаковым C
char
,int
,long
и 64-битные целые числа (G_TYPE_CHAR
,G_TYPE_UCHAR
,G_TYPE_INT
,G_TYPE_UINT
,G_TYPE_LONG
,G_TYPE_ULONG
,G_TYPE_INT64
, иG_TYPE_UINT64
); - логический тип (
G_TYPE_BOOLEAN
); - тип перечисления и тип «флаги», оба соответствующие C
enum
типа, но отличается тем, что последний используется только для битовых полей (G_TYPE_ENUM
иG_TYPE_FLAGS
); - типы для чисел с плавающей запятой одинарной и двойной точности IEEE , соответствующие C
float
иdouble
(G_TYPE_FLOAT
иG_TYPE_DOUBLE
); - строковый тип, соответствующий C
char *
(G_TYPE_STRING
); - непрозрачный тип указателя, соответствующий C
void *
(G_TYPE_POINTER
).
Классифицированные : встроенные фундаментальные типы
- тип базового класса для экземпляров
GObject
, корень стандартного дерева наследования классов (G_TYPE_OBJECT
) - базовый тип интерфейса, аналогичный типу базового класса, но представляющий корень стандартного интерфейса ( дерева наследования
G_TYPE_INTERFACE
) - тип для коробочных структур, которые используются для упаковки простых объектов-значений или внешних объектов в «коробки» с подсчетом ссылок (
G_TYPE_BOXED
) - тип «объектов спецификации параметров», которые используются в GObject для описания метаданных свойств объекта (
G_TYPE_PARAM
).
Типы, экземпляры которых могут быть созданы автоматически системой типов, называются экземплярами . Важной характеристикой этих типов является то, что первые байты любого экземпляра всегда содержат указатель на структуру класса (форму виртуальной таблицы ), связанную с типом экземпляра. По этой причине любой экземпляр типа должен быть классифицирован. И наоборот, любой неклассифицированный тип (например, целое число или строка ) не должен создавать экземпляры. С другой стороны, большинство классифицированных типов являются экземплярами, а некоторые, например типы интерфейсов, — нет.
Производные типы
[ редактировать ]Типы, производные от встроенных фундаментальных типов GObject, попадают в категорию примерно на четыре категории:
- Перечислимые типы и типы «флагов»
- В общем, каждый перечислимый тип и каждый тип битового поля на основе целого числа (т. е. каждый
enum
тип), который нужно использовать каким-либо образом, связанным с объектной системой (например, как тип свойства объекта), должен быть зарегистрирован в системе типов. Обычно код инициализации, который отвечает за регистрацию этих типов, генерируется автоматизированным инструментом под названиемglib-mkenums
[ 3 ] и хранится в отдельном файле. - Типы в штучной упаковке
- Некоторые структуры данных, которые слишком просты для того, чтобы их можно было превратить в полноценные типы классов (со всеми необходимыми накладными расходами), возможно, все равно придется зарегистрировать в системе типов. Например, у нас может быть класс, к которому мы хотим добавить
background-color
свойство, значения которого должны быть экземплярами структуры, которая выглядит какstruct color { int r, g, b; }
. Чтобы избежать необходимости создавать подклассыGObject
, мы можем создать коробочный тип для представления этой структуры и предоставить функции для копирования и освобождения. GObject поставляется с несколькими коробочными типами, обертывающими простые типы данных GLib. Другое использование коробочных типов — это способ обернуть посторонние объекты в контейнер с тегами, который система типов может идентифицировать и знать, как скопировать и освободить. - Непрозрачные типы указателей
- Иногда для объектов, которые не нужно ни копировать, ни подсчитывать ссылки, ни освобождать, даже коробочный тип будет излишним . Хотя такие объекты можно использовать в GObject, просто рассматривая их как непрозрачные указатели (
G_TYPE_POINTER
), часто бывает хорошей идеей создать производный тип указателя, документирующий тот факт, что указатели должны ссылаться на объект определенного типа, даже если об этом больше ничего не сказано. - Классы и типы интерфейсов
- Большинство типов в приложении GObject будут классами — в обычном объектно-ориентированном смысле этого слова — производными прямо или косвенно от корневого класса.
GObject
. Существуют также интерфейсы, которые, в отличие от классических Java в стиле интерфейсов , могут содержать реализованные методы. Таким образом, интерфейсы GObject можно описать как миксины .
Система обмена сообщениями
[ редактировать ]Система обмена сообщениями GObject состоит из двух взаимодополняющих частей: замыканий и сигналов .
- Замыкания
- Замыкание GObject — это обобщенная версия обратного вызова . Существует поддержка замыканий, написанных на C и C++, а также произвольных языках (если предусмотрены привязки). Это позволяет вызывать код, написанный (например) на Python и Java, через замыкание GObject.
- Сигналы
- Сигналы являются основным механизмом вызова замыканий. Объекты регистрируют прослушиватели сигналов с помощью системы типов, определяющей сопоставление между данным сигналом и данным замыканием. При отправке зарегистрированного сигнала вызывается закрытие этого сигнала. В GTK все собственные события графического интерфейса (такие как движение мыши и действия клавиатуры) могут генерировать сигналы GObject, на которые потенциально могут воздействовать слушатели.
Реализация класса
[ редактировать ]Каждый класс GObject реализуется как минимум двумя структурами: структурой класса и структурой экземпляра .
- Структура класса
- Структура класса соответствует виртуальной таблице класса C++. Все должно начинаться с классовой структуры суперкласса. После этого он будет содержать набор указателей на функции — по одному для каждого виртуального метода класса. Переменные, специфичные для класса, можно использовать для эмуляции членов класса.
- Структура экземпляра
- Структура экземпляра, которая будет существовать в одной копии для каждого экземпляра объекта, должна начинаться со структуры экземпляра суперкласса ( это гарантирует, что все экземпляры начинаются с указателя на структуру класса, поскольку все фундаментальные типы, создающие экземпляры, разделяют это свойство). После данных, принадлежащих суперклассу, структура может содержать любые переменные, специфичные для экземпляра, соответствующие переменным-членам C++.
Определение класса в среде GObject является сложным процессом, требующим большого количества стандартного кода, такого как ручное определение макросов приведения типов и непонятные заклинания регистрации типов. Кроме того, поскольку структура C не может иметь модификаторы доступа, такие как «public», «protected» или «private», необходимо использовать обходные пути для обеспечения инкапсуляции . Один из подходов заключается во включении указателя на частные данные, который обычно называется _priv
— в структуре экземпляра. Частная структура может быть объявлена в общедоступном заголовочном файле, но определена только в файле реализации, в результате чего частные данные непрозрачны для пользователей, но прозрачны для разработчика. Если частная структура зарегистрирована в GType, она будет автоматически выделена объектной системой. Действительно, даже нет необходимости включать _priv
указатель, если кто-то готов использовать заклинание G_TYPE_INSTANCE_GET_PRIVATE
каждый раз, когда необходимы личные данные.
Чтобы решить некоторые из этих сложностей, существует несколько языков более высокого уровня, которые компилируются из исходного кода в GObject на C. Язык программирования Vala использует синтаксис в стиле C# и предварительно обрабатывается в стандартный код C. GObject Builder, или GOB2 , предлагает синтаксис шаблонов, напоминающий Java .
Интроспекция GObject
[ редактировать ]- Интроспекция GObject (сокращенно GIR [ 4 ] ) — это промежуточный уровень интерфейса внешних функций между библиотеками C (с использованием GObject) и языковыми привязками, ср. Список языковых привязок для GTK .
Использование
[ редактировать ]Комбинация C и GObject используется во многих успешных проектах бесплатного программного обеспечения , таких как рабочий стол GNOME , набор инструментов GTK и программа манипулирования изображениями GIMP .
Хотя многие приложения GObject полностью написаны на C, система GObject хорошо сопоставляется с собственными объектными системами многих других языков, таких как C++ , Java , Ruby , Python , Common Lisp и .NET / Mono . В результате обычно сравнительно безболезненно создавать языковые привязки для хорошо написанных библиотек, использующих инфраструктуру GObject.
Однако написание кода GObject на языке C является относительно многословным. Изучение библиотеки требует много времени, и программисты с опытом работы с объектно-ориентированными языками высокого уровня часто находят несколько утомительным работать с GObject в C. Например, создание подкласса (даже просто подкласса GObject
) может потребовать написания и/или копирования больших объемов шаблонного кода . [ 5 ] Однако использование Vala , языка, который предназначен в первую очередь для работы с GObject и который преобразуется в C, вероятно, улучшит работу с GObject или написание библиотек на основе GObject.
Хотя на самом деле они не являются первоклассными объектами (в GType нет реальных метатипов), такие метаобъекты , как классы и интерфейсы, создаются приложениями GObject во время выполнения и обеспечивают хорошую поддержку самоанализа . Интроспективные возможности используются языковыми привязками и приложениями для разработки пользовательского интерфейса, такими как Glade, чтобы позволить выполнять такие действия, как загрузка общей библиотеки , предоставляющей класс GObject (обычно какой-то виджет , в случае Glade), а затем получать список всех свойств. класса, в комплекте с информацией о типе и документацией струны.
Сравнение с другими объектными системами
[ редактировать ]Возможно, этот раздел содержит оригинальные исследования . ( декабрь 2011 г. ) |
Поскольку GObject предоставляет практически полную объектную систему для C [ нужна ссылка ] его можно рассматривать как альтернативу языкам, производным от C, таким как C++ и Objective-C . (Хотя оба они также предлагают множество других функций, помимо соответствующих объектных систем.) Легко заметить разницу между C++ и GObject заключается в том, что GObject (как и Java) не поддерживает множественное наследование . [ 6 ]
Использование GObject функции выделения памяти g_malloc() из GLib приведет к безоговорочному выходу программы при исчерпании памяти, в отличие от malloc C++ () библиотеки C, new и других распространенных распределителей памяти, которые позволяют программе справиться с ней или даже полностью восстановиться. из ситуаций нехватки памяти без простого сбоя. [ 7 ] Это, как правило, препятствует включению GObject в программное обеспечение, где важна устойчивость к ограниченной памяти или где обычно обрабатывается очень много или очень больших объектов. g_try_new() можно использовать, когда выделение памяти с большей вероятностью завершится неудачно (например, для большого объекта), но это не может гарантировать, что выделение не завершится неудачно в другом месте кода. [ 8 ]
Еще одно важное отличие заключается в том, что, хотя C++ и Objective-C являются отдельными языками, GObject является строго библиотекой и, как таковой, не вводит никакого нового синтаксиса или интеллектуальных возможностей компилятора. Например, при написании кода C на основе GObject часто необходимо выполнить явное повышающее приведение . [ нужна ссылка ] Следовательно, «C с GObject», также называемый «C со вкусом glib», рассматриваемый как язык, отдельный от простого C, является строгим расширенным набором простого C — как Objective C, но в отличие от C ++.
На платформах, где нет стандартного ABI , работающего во всех компиляторах C++ (что обычно не так, поскольку обычно используются либо Itanium ABI, либо Microsoft ABI), библиотека, скомпилированная с помощью одного компилятора C++, не всегда может вызвать библиотека, скомпилированная с другой. [ нужна ссылка ] Если такая совместимость требуется, методы C++ необходимо экспортировать как простые функции C, что частично противоречит цели объектной системы C++. [ нужна ссылка ] Проблема возникает отчасти потому, что разные компиляторы C++ используют разные виды искажения имен , чтобы гарантировать уникальность всех экспортируемых символов. (Это необходимо, поскольку, например, два разных класса могут иметь функции-члены с одинаковыми именами, одно имя функции может быть перегружено несколько раз или функции с одинаковыми именами могут появляться в разных пространствах имен , но в объектном коде такие перекрытия не допускаются.) [ нужна ссылка ] Напротив, поскольку C не поддерживает какую-либо форму перегрузки или пространства имен, авторы библиотек C обычно используют явные префиксы, чтобы гарантировать глобальную уникальность своих экспортируемых имен. [ нужна ссылка ] Следовательно, несмотря на объектно-ориентированность, библиотека на основе GObject, написанная на C, всегда будет использовать одни и те же имена внешних символов независимо от того, какой компилятор используется.
Возможно, самым глубоким отличием является акцент GObject на сигналах (называемых событиями на других языках). [ нужна ссылка ] Этот акцент обусловлен тем фактом, что GObject был специально разработан для удовлетворения потребностей набора инструментов GUI. Хотя для большинства объектно-ориентированных языков существуют библиотеки сигналов, в случае GObject они встроены в объектную систему. Из-за этого типичное приложение GObject будет иметь тенденцию использовать сигналы в гораздо большей степени, чем приложение, не использующее GObject, что делает компоненты GObject гораздо более инкапсулированными и пригодными для повторного использования, чем те, которые используют простой C++ или Java. [ нужна ссылка ] [ по мнению кого? ] При использовании glibmm / gtkmm , официальных оболочек C++ для Glib/GTK соответственно, родственный проект libsigc++ позволяет легко использовать базовые сигналы GObject с использованием стандарта C++. Конечно, практически на всех платформах доступны и другие реализации сигналов, хотя иногда требуется дополнительная библиотека, например Boost.Signals2 для C++.
См. также
[ редактировать ]- Vala — язык программирования на основе GObject с синтаксисом, подобным C# . Компилятор исходного в C. кода
Ссылки
[ редактировать ]- ^ «Справочное руководство по GObject» .
- ^ «Справочное руководство GObject — стабильная версия» .
- ^ «glib-mkenums, Справочное руководство по GObject» .
- ^ «Самоанализ, Краткое содержание» . Gnome Developer, Рекомендации по программированию — конкретные инструкции . Проверено 9 августа 2020 г.
- ^ «Как определить и реализовать новый GObject» . gnome.org . Проверено 27 июля 2013 г.
- ^ «С++ — Почему была создана система GObject?» . Переполнение стека . Проверено 16 ноября 2019 г.
- ^ «Распределение памяти: Справочное руководство GLib» . http://developer.gnome.org . Проверено 16 ноября 2019 г.
- ^ «Распределение памяти: Справочное руководство GLib» . http://developer.gnome.org . Проверено 17 ноября 2019 г.