GОбъект

Библиотека свободного программного обеспечения
GОбъект
Разработчик(и)Проект GNOME
Первоначальный выпуск11 марта 2002 г. ; 22 года назад ( 2002-03-11 )
Написано вС
Операционная системаКроссплатформенный
Доступно вМногоязычный [ какой? ]
ТипБиблиотека программного обеспечения
ЛицензияGNU LGPL
Веб-сайтDeveloper.gnome.org/gobject/stable/
Так же как библиотека GNU C служит оболочкой для системных вызовов ядра Linux , так и библиотеки, входящие в состав GLib (GObject, Glib , GModule, GThread и GIO ), служат дополнительными оболочками для своих конкретных задач.

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

Отношение к 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);
  • типы, соответствующие знаковым и беззнаковым char, int, long, и 64-битным целым числам языка C ( 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 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, значения которого должны быть экземплярами структуры, которая выглядит как . Чтобы избежать необходимости подкласса , мы можем создать коробочный тип для представления этой структуры и предоставить функции для копирования и освобождения. 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 все собственные события GUI (такие как движение мыши и действия клавиатуры) могут генерировать сигналы GObject для потенциального действия прослушивателей.

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

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

Структура класса
Структура класса соответствует vtable класса 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

Использование

Сочетание 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), а затем получать список всех свойств класса, полный с информацией о типе и строками документации.

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

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

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

Другое важное отличие заключается в том, что, хотя C++ и Objective-C являются отдельными языками, GObject — это строго библиотека и, как таковая, не вводит никакого нового синтаксиса или интеллекта компилятора. Например, при написании кода C на основе GObject часто необходимо выполнять явное приведение типов . [ требуется цитата ] Следовательно, «C с GObject», также называемый «glib-flavored C», рассматриваемый как язык, отдельный от простого 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. ^ «Справочное руководство GObject».
  2. ^ «Справочное руководство GObject — Стабильная версия».
  3. ^ "glib-mkenums, Справочное руководство GObject".
  4. ^ "Introspection, Summary". Gnome Developer, Programming Guidelines - Specific How-Tos . Получено 9 августа 2020 г.
  5. ^ "Как определить и реализовать новый GObject". gnome.org . Получено 27 июля 2013 г. .
  6. ^ "c++ - Зачем была создана система GObject?". Stack Overflow . Получено 16.11.2019 .
  7. ^ "Выделение памяти: Справочное руководство по GLib". developer.gnome.org . Получено 16.11.2019 .
  8. ^ "Выделение памяти: Справочное руководство по GLib". developer.gnome.org . Получено 17.11.2019 .
  • Справочное руководство GObject (и учебник)
  • Учебное пособие GObject, август 2004 г.
  • GOB2 — GObject Builder
  • Домашняя страница Вала
Взято с "https://en.wikipedia.org/w/index.php?title=GObject&oldid=1257250374#GObject_Introspection"