stringtranslate.com

GОбъект

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

Классифицированные встроенные фундаментальные типы:

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

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

Типы, производные от встроенных фундаментальных типов 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 все собственные события графического интерфейса (такие как движение мыши и действия клавиатуры) могут генерировать сигналы 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

Применение

Комбинация 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», также называемый «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++.

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

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

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

Внешние ссылки