GObject - GObject

GObject
Разработчики)Проект GNOME
изначальный выпуск11 марта 2002 г.; 18 лет назад (2002-03-11)
Стабильный выпуск2.64.4 (2 июля 2020 г.; 4 месяца назад (2020-07-02)) [±][1]
Написано вC
Операционная системаКроссплатформенность
Доступно вМногоязычный[который? ]
ТипПрограммная библиотека
ЛицензияGNU LGPL
Интернет сайтразработчик.гном.org/ gobject/стабильный/
Поскольку Библиотека GNU C служит оберткой для Ядро Linux системные вызовы, как и библиотеки, входящие в GLib (GObject, Бойко, GModule, GThread и GIO ) служат дополнительными оболочками для их конкретных задач.

В Система объектов GLib, или же GObject, это свободный библиотека программного обеспечения предоставление портативного объектная система и прозрачная межъязыковая совместимость. GObject предназначен для использования как непосредственно в C программы для предоставления объектно-ориентированных API на основе C и через привязки на другие языки, чтобы обеспечить прозрачную межъязыковую совместимость, например PyGObject.

GObject Introspection

История

В зависимости только от GLib и libc, GObject является краеугольным камнем ГНОМ и используется повсюду GTK, Панго, АТК, и на самом высоком уровне ГНОМ библиотеки вроде GStreamer и приложения. До GTK + 2.0 код, аналогичный GObject, был частью кодовой базы GTK. (Имя «GObject» еще не использовалось - общий базовый класс назывался GtkObject.)

В выпуске GTK + 2.0 объектная система была выделена в отдельную библиотеку из-за ее общей полезности. При этом большинство не-GUI -конкретные части GtkObject класс были переведены в GObject, новый общий базовый класс. Библиотека GObject, существующая как отдельная библиотека с 11 марта 2002 г. (дата выпуска GTK + 2.0), теперь используется многими программами без графического интерфейса пользователя, такими как командная строка и сервер Приложения.

Отношение к GLib

Хотя у GObject есть свой отдельный набор документации[3] и обычно компилируется в собственный общая библиотека файл, исходный код GObject находится в GLib дерево исходных текстов и распространяется вместе с GLib. По этой причине GObject использует номера версий GLib и обычно упаковывается вместе с GLib (например, Debian помещает GObject в свой libglib2.0 семейство пакетов).

Система типов

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

Система типов знает, как копировать, присваивать и уничтожать значения, принадлежащие любому из зарегистрированных типов. Это тривиально для таких типов, как целые числа, но многие сложные объекты подсчитанный по ссылкам, в то время как некоторые из них сложны, но не учитывают количество ссылок. Когда система типов «копирует» объект с подсчетом ссылок, она обычно просто увеличивает счетчик ссылок, тогда как при копировании сложного объекта без подсчета ссылок (например, строки) она обычно создает фактическую копию с помощью распределение памяти.

Эта базовая функциональность используется для реализации GValue, тип универсального контейнера, который может содержать значения любого типа, известного системе типов. Такие контейнеры особенно полезны при взаимодействии с динамически типизированными языковыми средами, в которых все собственные значения находятся в таких помеченный типом контейнеры.

Основные типы

Типы, которые не связаны классы называются неклассифицированный. Эти типы вместе со всеми типами, соответствующими той или иной форме корневой класс, известны как основные типы: типы, от которых происходят все остальные типы. Они составляют относительно замкнутый набор, но хотя от обычного пользователя не ожидается, что он создаст свои собственные основные типы, возможность существует и использовалась для создания собственных иерархии классов - т.е. иерархии классов, не основанные на GObject учебный класс.

Начиная с GLib 2.9.2,[4] то неклассифицированный встроенные основные типы:

  • пустой тип, соответствующий C пустота (G_TYPE_NONE);
  • типы, соответствующие C со знаком и без знака char, int, длинная, и 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 перечислить типа, но отличается тем, что последний используется только для битовые поля (G_TYPE_ENUM и G_TYPE_FLAGS);
  • типы для одинарной и двойной точности IEEE плавает, соответствующие C плавать и двойной (G_TYPE_FLOAT и G_TYPE_DOUBLE);
  • строковый тип, соответствующий C символ * (G_TYPE_STRING);
  • непрозрачный тип указателя, соответствующий C пустота * (G_TYPE_POINTER).

В классифицированный встроенные основные типы:

  • тип базового класса для экземпляров GObject, корень стандартного дерева наследования классов (G_TYPE_OBJECT)
  • базовый тип интерфейса, аналогичный типу базового класса, но представляющий корень стандарта интерфейс дерево наследования (G_TYPE_INTERFACE)
  • тип для в штучной упаковке структуры, которые используются для обертывания простых объектов значений или посторонних объектов в «ящики» со счетчиком ссылок (G_TYPE_BOXED)
  • тип для «объектов спецификации параметров», которые используются в GObject для описания метаданные для свойств объекта (G_TYPE_PARAM).

Типы, которые могут быть созданы автоматически системой типов, называются инстанцируемый. Важной характеристикой этих типов является то, что первые байты любого экземпляра всегда содержат указатель на структура класса (форма виртуальный стол ) связанный с типом экземпляра. По этой причине любой экземплярный тип должен быть классифицирован. Напротив, любой неклассифицированный тип (например, целое число или нить) не должно быть инстанцируемым. С другой стороны, большинство классифицированных типов могут создавать экземпляры, но некоторые, например типы интерфейсов, нет.

Производные типы

Типы, производные от встроенных фундаментальных типов GObject, можно разделить на четыре категории:

Нумерованные типы и типы «флаги»
В общем, каждый перечислимый тип и каждый тип битового поля на основе целых чисел (т. Е. Каждый перечислить type), который желают использовать каким-либо образом, связанным с системой объектов - например, как тип свойства объекта - должен быть зарегистрирован в системе типов. Обычно код инициализации, который заботится о регистрации этих типов, генерируется автоматическим инструментом, называемым glib-mkenums[5] и хранится в отдельном файле.
Типы в штучной упаковке
Некоторые структуры данных, которые слишком просты для того, чтобы их можно было сделать полноценными типами классов (со всеми возникающими накладными расходами), возможно, все же потребуется зарегистрировать в системе типов. Например, у нас может быть класс, к которому мы хотим добавить фоновый цвет свойство, значения которого должны быть экземплярами структуры, которая выглядит как структура цвет { int р, грамм, б; }. Чтобы избежать подкласса GObject, мы можем создать коробочный тип для представления этой структуры и предоставления функций для копирования и освобождения. GObject поставляется с несколькими упакованными типами, обертывающими простые типы данных GLib. Другое использование упакованных типов - это способ обернуть посторонние объекты в помеченный контейнер, который система типов может идентифицировать и будет знать, как копировать и освобождать.
Типы непрозрачных указателей
Иногда для объектов, которые не нужно ни копировать, ни подсчитывать ссылки, ни освобождать, даже упакованный тип будет перебор. Хотя такие объекты можно использовать в GObject, просто рассматривая их как непрозрачные указатели (G_TYPE_POINTER), часто бывает хорошей идеей создать производный тип указателя, документируя тот факт, что указатели должны ссылаться на конкретный вид объекта, даже если об этом больше ничего не говорится.
Типы классов и интерфейсов
Большинство типов в приложении GObject будут классами - в обычном объектно-ориентированном смысле слова - производными прямо или косвенно от корневого класса, GObject. Также есть интерфейсы, которые в отличие от классических Ява -стилевые интерфейсы, могут содержать реализованные методы. Таким образом, интерфейсы GObject можно описать как миксины.

Система обмена сообщениями

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

Закрытие
Замыкание GObject - это обобщенная версия Перезвони. Существует поддержка замыканий, написанных на C и C ++, а также на произвольных языках (при наличии привязок). Это позволяет запускать код, написанный (например) на Python и Java через замыкание GObject.
Сигналы
Сигналы - это основной механизм, с помощью которого вызываются закрытия. Объекты регистрируют слушателей сигналов с помощью системы типов, определяя отображение между заданным сигналом и заданным замыканием. При выдаче зарегистрированного сигнала происходит закрытие этого сигнала. В GTK все собственные события графического интерфейса (такие как движение мыши и действия клавиатуры) могут генерировать сигналы GObject для слушателей, которые потенциально могут действовать.

Реализация класса

Каждый класс GObject реализуется как минимум двумя структурами: структура класса и структура экземпляра.

Структура класса
Структура классов соответствует vtable класса C ++. Он должен начинаться со структуры классов суперкласса. После этого он будет содержать набор указателей на функции - по одному для каждого виртуальный метод класса. Переменные, зависящие от класса, можно использовать для имитации членов класса.
Структура экземпляра
Структура экземпляра, которая будет существовать в одной копии для каждого экземпляра объекта, должна начинаться с структуры экземпляра объекта суперкласс (это гарантирует, что все экземпляры начинаются с указателя на структуру класса, поскольку все фундаментальные экземпляры типов разделяют это свойство). После данных, принадлежащих суперклассу, структура может содержать любые переменные, зависящие от экземпляра, соответствующие переменным-членам C ++.

Определение класса в структуре GObject - сложная задача, требующая большого количества шаблон код, такой как ручные определения макросов приведения типов и неясные заклинания регистрации типов. Кроме того, поскольку структура C не может иметь модификаторы доступа, такие как «общедоступный», «защищенный» или «частный», необходимо использовать обходные пути для предоставления инкапсуляция. Один из подходов - включить указатель на личные данные, которые обычно называются _priv - в структуре экземпляра. В частная структура могут быть объявлены в общедоступном файле заголовка, но определены только в файле реализации, в результате чего личные данные будут непрозрачными для пользователей, но прозрачными для разработчика. Если частная структура зарегистрирована в GType, она будет автоматически выделена объектной системой. Действительно, даже не обязательно включать _priv указатель, если кто-то хочет использовать заклинание G_TYPE_INSTANCE_GET_PRIVATE каждый раз, когда требуются личные данные.

Для решения некоторых из этих сложностей существует несколько языков более высокого уровня, которые компиляция из исходного кода в исходный в GObject в C. Язык программирования Вала использует C # -style и предварительно обрабатывается в ваниль Код C. GObject Builder или GOB2, предлагает синтаксис шаблона, напоминающий Ява.

Применение

Комбинация C и GObject используется во многих успешных бесплатно программное обеспечение проекты, такие как ГНОМ рабочий стол, GTK инструментарий и GIMP программа для обработки изображений.

Хотя многие приложения GObject полностью написаны на C, система GObject хорошо согласуется с собственными объектными системами многих других языков, например C ++, Ява, Рубин, Python, Common Lisp, и .СЕТЬ /Мононуклеоз. В результате обычно относительно безболезненно создавать языковые привязки для хорошо написанных библиотек, использующих инфраструктуру GObject.

Однако написание кода GObject на C в первую очередь относительно многословно. Библиотека требует много времени для изучения, и программисты с опытом высокий уровень объектно-ориентированные языки часто находят несколько утомительным работать с GObject в C.Например, создание подкласса (даже просто подкласса GObject) может потребоваться написание и / или копирование большого количества шаблонный код.[6] Однако, используя Вала, язык, который предназначен в первую очередь для работы с GObject и который конвертируется в C, вероятно, облегчит работу с GObject или написание библиотек на основе GObject.

Хотя они не совсем первоклассные объекты (в GType нет реальных метатипов), метаобъекты подобные классы и интерфейсы создаются приложениями GObject во время выполнения и обеспечивают хорошую поддержку самоанализ. Интроспективные возможности используются языковыми привязками и приложениями для разработки пользовательского интерфейса, такими как Поляна чтобы позволить делать такие вещи, как загрузка общая библиотека который предоставляет класс GObject - обычно какой-то виджет в случае Glade - а затем получить список всех свойств класса с информацией о типе и строками документации.

Сравнение с другими объектными системами

Поскольку GObject предоставляет в основном полную объектную систему для C[нужна цитата ], его можно рассматривать как альтернативу языкам, производным от C, таким как C ++ и Цель-C. (Хотя оба они также предлагают множество других функций, помимо соответствующих объектных систем.) Легко наблюдаемая разница между C ++ и GObject заключается в том, что GObject (например, Java) не поддерживает множественное наследование.[7]

GObject использует GLib Функция выделения памяти g_malloc () заставит программу безоговорочно завершить работу при исчерпании памяти, в отличие от библиотеки C маллок (), C ++ новый и другие распространенные распределители памяти, которые позволяют программе справляться с ситуациями нехватки памяти или даже полностью восстанавливаться из них без простого сбоя.[8] Это, как правило, работает против включения GObject в программное обеспечение, где важна устойчивость перед лицом ограниченной памяти или где обычно обрабатывается очень много или очень большие объекты. G_try_new () можно использовать, когда с большей вероятностью произойдет сбой выделения памяти (например, для большого объекта), но это не может гарантировать, что выделение не завершится сбоем в другом месте кода.[9]

Еще одно важное отличие состоит в том, что, хотя C ++ и Objective-C являются отдельными языками, GObject является строго библиотекой и поэтому не вводит новый синтаксис или интеллект компилятора. Например, при написании кода C на основе GObject часто необходимо выполнить явное восходящий.[нужна цитата ] Следовательно, «C с GObject», рассматриваемый как язык, отдельный от простого 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 ++.

Смотрите также


Рекомендации

  1. ^ Витналл, Филип (2 июля 2020 г.). "glib 2.64.4". Ftp-релиз GNOME (Список рассылки). Получено 14 августа 2020.
  2. ^ «Самоанализ, резюме». Разработчик Gnome, Руководство по программированию - Конкретные инструкции. Получено 9 августа 2020.
  3. ^ "Справочное руководство GObject".
  4. ^ "Справочное руководство GObject - стабильная".
  5. ^ "glib-mkenums, Справочное руководство по GObject".
  6. ^ «Как определить и реализовать новый GObject». gnome.org. Получено 27 июля 2013.
  7. ^ "c ++ - Почему была создана система GObject?". Переполнение стека. Получено 2019-11-16.
  8. ^ «Распределение памяти: Справочное руководство по GLib». developer.gnome.org. Получено 2019-11-16.
  9. ^ «Распределение памяти: Справочное руководство по GLib». developer.gnome.org. Получено 2019-11-17.

внешняя ссылка