Из Википедии, бесплатной энциклопедии
Перейти к навигации Перейти к поиску
Поскольку библиотека GNU C служит оболочкой для системных вызовов ядра Linux , так и библиотеки , входящие в состав GLib (GObject, Glib , GModule , GThread и GIO ), служат дополнительными оболочками для своих конкретных задач.

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

GObject Introspection [ править ]

  • Самоанализ GObject (сокращенно GIR [2] ) - это промежуточный уровень между библиотеками C (с использованием GObject) и языковыми привязками, ср. Список языковых привязок для GTK .

История [ править ]

GObject, зависящий только от GLib и libc , является краеугольным камнем GNOME и используется в GTK , Pango , ATK и большинстве высокоуровневых библиотек GNOME, таких как GStreamer и приложения. До GTK + 2.0 код, похожий на GObject, был частью кодовой базы GTK. (Имя «GObject» еще не использовалось - был вызван общий базовый класс GtkObject.)

В выпуске GTK + 2.0 объектная система была выделена в отдельную библиотеку из-за ее общей полезности. В процессе этого большинство частей класса , не связанных с графическим интерфейсом пользователя,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классе.

По состоянию на БОЙКОМ 2.9.2 [4] , не классифицировано встроенный основных типов:

  • пустой тип, соответствующий 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);
  • тип перечисления и тип «флаги», оба соответствуют enumтипу C , но отличаются тем, что последний используется только для битовых полей ( G_TYPE_ENUMи G_TYPE_FLAGS);
  • типы для чисел с плавающей запятой IEEE одинарной и двойной точности , соответствующие C floatи double( G_TYPE_FLOATи G_TYPE_DOUBLE);
  • строковый тип, соответствующий C's char *( G_TYPE_STRING);
  • тип непрозрачного указателя, соответствующий C's void *( G_TYPE_POINTER).

Оценен встроенные основных типов:

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

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

Производные типы [ править ]

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

Перечислимые типы и типы «флажков»
В общем, каждый перечислимый тип и каждый тип битового поля на основе целых чисел (то есть каждый enumтип), который нужно использовать каким-либо образом, связанным с системой объектов - например, как тип свойства объекта - должен быть зарегистрирован с помощью система типов. Обычно код инициализации, который заботится о регистрации этих типов, генерируется автоматическим инструментом под названием glib-mkenums[5] и сохраняется в отдельном файле.
Типы в штучной упаковке
Некоторые структуры данных, которые слишком просты для того, чтобы их можно было сделать полноценными типами классов (со всеми возникающими накладными расходами), возможно, все же потребуется зарегистрировать в системе типов. Например, у нас может быть класс, к которому мы хотим добавить background-colorсвойство, значения которого должны быть экземплярами структуры, которая выглядит так . Чтобы избежать создания подклассов , мы можем создать упакованный тип для представления этой структуры и предоставить функции для копирования и освобождения. GObject поставляется с несколькими упакованными типами, обертывающими простые типы данных GLib. Другое использование упакованных типов - это способ обернуть посторонние объекты в помеченный контейнер, который система типов может идентифицировать и будет знать, как копировать и освобождать.struct color { int r, g, b; }GObject
Типы непрозрачных указателей
Иногда для объектов, которые не нужно ни копировать, ни подсчитывать ссылки, ни освобождать, даже упакованный тип будет излишним . Хотя такие объекты можно использовать в GObject, просто рассматривая их как непрозрачные указатели ( G_TYPE_POINTER), часто бывает хорошей идеей создать производный тип указателя, документируя тот факт, что указатели должны ссылаться на конкретный вид объекта, даже если ничто другое не является сказал об этом.
Типы классов и интерфейсов
Большинство типов в приложении GObject будут классы - в обычном объектно-ориентированном смысле этого слова - производные прямо или косвенно из корневого класса GObject. Существуют также интерфейсы, которые, в отличие от классических интерфейсов в стиле Java , могут содержать реализованные методы. Таким образом, интерфейсы 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. Язык программирования Vala использует синтаксис в стиле C # и предварительно обрабатывается в ванильный код C. GObject Builder или GOB2 предлагает синтаксис шаблона, напоминающий Java .

Использование [ править ]

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

Хотя многие приложения GObject полностью написаны на C, система GObject хорошо отображается в собственных объектных системах многих других языков, таких как C ++ , Java , Ruby , Python , Common Lisp и .NET / Mono . В результате создание языковых привязок для хорошо написанных библиотек, использующих инфраструктуру GObject, обычно относительно безболезненно .

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

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

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

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

Использование GObject функции выделения памяти g_malloc () GLib приведет к тому, что программа будет безоговорочно завершена при исчерпании памяти, в отличие от библиотеки C malloc (), нового 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 ++.

См. Также [ править ]

  • Vala - язык программирования на основе GObject с синтаксисом C # . Источник в исходный компилятор на C .
  • Genie - альтернативный синтаксический анализатор для компилятора Vala в стиле Python


Ссылки [ править ]

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

Внешние ссылки [ править ]

  • Справочное руководство GObject (и учебник)
  • Учебник GObject, август 2004 г.
  • GOB2 - конструктор GObject
  • Вала Домашняя страница