Разработчик(и) | Проект GNOME |
---|---|
Первоначальный выпуск | 11 марта 2002 г. ( 2002-03-11 ) |
Написано в | С |
Операционная система | Кроссплатформенный |
Доступно в | Многоязычный [ какой? ] |
Тип | Библиотека программного обеспечения |
Лицензия | GNU LGPL |
Веб-сайт | Developer.gnome.org/gobject/stable/ |
Система объектов 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 программами, такими как командная строка и серверные приложения.
Хотя GObject имеет свой собственный отдельный набор документации [1] и обычно компилируется в свой собственный файл общей библиотеки , исходный код GObject находится в исходном дереве GLib и распространяется вместе с GLib. По этой причине GObject использует номера версий GLib и обычно упаковывается вместе с GLib (например, Debian помещает GObject в свое libglib2.0
семейство пакетов).
На самом базовом уровне фреймворка GObject лежит общая и динамическая система типов , называемая GType. Система GType содержит описание времени выполнения всех объектов, позволяя связующему коду облегчать привязки нескольких языков. Система типов может обрабатывать любую унаследованную структуру класса, в дополнение к неклассифицированным типам, таким как непрозрачные указатели , строки и целые числа и числа с плавающей точкой различного размера .
Система типов знает, как копировать, назначать и уничтожать значения, принадлежащие любому из зарегистрированных типов. Это тривиально для типов вроде целых чисел, но многие сложные объекты являются объектами с подсчетом ссылок , в то время как некоторые являются сложными, но не с подсчетом ссылок. Когда система типов «копирует» объект с подсчетом ссылок, она обычно просто увеличивает его счетчик ссылок, тогда как при копировании сложного объекта без подсчета ссылок (например, строки) она обычно создает фактическую копию, выделяя память .
Эта базовая функциональность используется для реализации GValue
, типа универсального контейнера, который может содержать значения любого типа, известного системе типов. Такие контейнеры особенно полезны при взаимодействии с динамически типизированными языковыми средами, в которых все собственные значения находятся в таких контейнерах с тегами типов .
Типы, не имеющие связанных классов, называются неклассифицированными . Эти типы, вместе со всеми типами, соответствующими некоторой форме корневого класса, известны как фундаментальные типы : типы, из которых выводятся все остальные типы. Они составляют относительно закрытый набор, но хотя от обычного пользователя не ожидается создания собственных фундаментальных типов, такая возможность существует и использовалась для создания пользовательских иерархий классов — т. е. иерархий классов, не основанных на GObject
классе.
Начиная с GLib 2.9.2, [2] неклассифицированными встроенными фундаментальными типами являются:
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
);float
и double
( G_TYPE_FLOAT
и G_TYPE_DOUBLE
);char *
( G_TYPE_STRING
);void *
( G_TYPE_POINTER
).Классифицированные встроенные фундаментальные типы :
GObject
, корень стандартного дерева наследования классов ( G_TYPE_OBJECT
)G_TYPE_INTERFACE
( )G_TYPE_BOXED
)G_TYPE_PARAM
).Типы, которые могут быть инстанциированы автоматически системой типов, называются инстанцируемыми . Важной характеристикой этих типов является то, что первые байты любого экземпляра всегда содержат указатель на структуру класса (форму виртуальной таблицы ), связанную с типом экземпляра. По этой причине любой инстанцируемый тип должен быть классифицирован. Напротив, любой неклассифицированный тип (такой как целое число или строка ) должен быть не инстанцируемым. С другой стороны, большинство классифицированных типов инстанцируемы, но некоторые, такие как типы интерфейсов, — нет.
Типы, которые являются производными от встроенных фундаментальных типов GObject, можно условно разделить на четыре категории:
enum
тип), который вы хотите использовать каким-либо образом, связанным с объектной системой, например, как тип свойства объекта, должны быть зарегистрированы в системе типов. Обычно код инициализации, который отвечает за регистрацию этих типов, генерируется автоматизированным инструментом, называемым glib-mkenums
[3], и сохраняется в отдельном файле.background-color
, значения которого должны быть экземплярами структуры, которая выглядит как . Чтобы избежать необходимости подкласса , мы можем создать коробочный тип для представления этой структуры и предоставить функции для копирования и освобождения. GObject поставляется с несколькими коробочными типами, оборачивающими простые типы данных GLib. Другое применение коробочных типов — это способ обернуть внешние объекты в помеченный контейнер, который система типов может идентифицировать и будет знать, как копировать и освобождать.struct color { int r, g, b; }
GObject
G_TYPE_POINTER
), часто бывает полезно создать производный тип указателя, документируя тот факт, что указатели должны ссылаться на определенный вид объекта, даже если об этом больше ничего не сказано.GObject
. Существуют также интерфейсы, которые, в отличие от классических интерфейсов в стиле Java , могут содержать реализованные методы. Таким образом, интерфейсы GObject можно описать как миксины .Система обмена сообщениями GObject состоит из двух взаимодополняющих частей: замыканий и сигналов .
Каждый класс GObject реализуется как минимум двумя структурами: структурой класса и структурой экземпляра .
Определение класса в фреймворке GObject является сложным и требует большого количества шаблонного кода, такого как ручные определения макросов приведения типов и неясные заклинания регистрации типов. Кроме того, поскольку структура C не может иметь модификаторов доступа, таких как «public», «protected» или «private», необходимо использовать обходные пути для обеспечения инкапсуляции . Один из подходов заключается в том, чтобы включить указатель на закрытые данные — традиционно называемые _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
) может потребовать написания и/или копирования большого количества шаблонного кода . [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, 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++.