Библиотека сайта rus-linux.net
Программирование с использованием gtkmm 3. Создание с помощью утилиты gmmproc оберток для разработанных с использованием языка программирования C библиотек
Оригинал: Programming with gtkmm 3Авторы: Murray Cumming, Bernhard Rieder, Jonathon Jongsma, Ole Laursen, Marko Anastasov, Daniel Elstner, Chris Vine, David King, Pedro Ferreira, Kjell Ahlstedt
Дата публикации: 15 Октября 2013 г.
Перевод: А.Панин
Дата перевода: 25 Апреля 2014 г.
Приложение G. Создание с помощью утилиты gmmproc оберток для разработанных с использованием языка программирования C библиотек
G.3. Файлы с расширениями .hg и .ccg
Файлы исходного кода с расширениями .hg и .ccg очень похожи на файлы исходного кода языка программирования C++ с расширениями .h и .cc, но они содержат дополнительные макросы, такие, как _CLASS_GOBJECT() и _WRAP_METHOD(), с помощью которых утилита gmmproc генерирует соответствующий исходный код на языке C++ обычно с таким же расположением заголовочных файлов. Любой дополнительный код на языке C++ будет скопирован в неизменном виде в соответствующий файл с расширением .h или .cc.
В рамках файла с расширением .hg обычно осуществляется подключение некоторых заголовочных файлов с последующим объявлением класса, в котором используются некоторые макросы для описания API или поведения класса. Например, файл button.hg из исходного кода gtkmm выглядит примерно следующим образом:
- _DEFS()
- Указывает целевую директорию для сгенерированных файлов исходного кода и имя основного файла с расширением
.defs, который должен быть разобран с помощью утилитыgmmproc. - _PINCLUDE()
- Сообщает утилите
gmmprocо необходимости подключения заголовочного файла к сгенерированному файлуprivate/button_p.h. - _CLASS_GTKOBJECT()
- Сообщает утилите
gmmprocо необходимости добавления объявлений типов с использованием операторовtypedef, конструкторов и стандартных методов для данного класса, характерных для оберток классов виджетов. - _IMPLEMENTS_INTERFACE()
- Сообщает утилите
gmmprocо необходимости добавления кода инициализации для интерфейса. - _CTOR_DEFAULT
- Добавление стандартного конструктора.
- _WRAP_METHOD(), _WRAP_SIGNAL() и _WRAP_PROPERTY()
- Добавление методов для создания оберток над функциями API языка программирования C.
.h и .cc будут генерироваться на основе файлов .hg и .ccg путем обработки последних с помощью утилиты gmmproc, причем это будет делаться автоматически в случае использования описанной структуры директорий для сборки:
$ cd gtk/src $ /usr/lib/glibmm-2.4/proc/gmmproc -I ../../tools/m4 --defs . button . ./../gtkmm
Обратите внимание на то, что мы передали утилите gmmproc путь к файлам преобразований с расширением .m4, путь к файлам с расширением .defs, имя файла с расширением .hg, путь к директории исходного кода, а также путь к директории для сохранения сгенерированных файлов.
Вы должны избегать подключения заголовочных файлов, созданных с намерением последующего использования языка программирования C, из вашего заголовочного файла, созданного с намерением последующего использования языка программирования C++, избегать использования глобального пространства имен, а также избегать экспортирования неиспользуемых публичных API. Но вам в любом случае придется подключать необходимые заголовочные файлы, созданные с намерением последующего использования языка программирования C, из вашего файла с расширением .ccg.
Макросы будут описаны более подробно в следующих разделах.
G.3.1. Преобразования типов с использованием файлов преобразований с расширением .m4
.hg и .cgg макросов обычно требуется информация о том, как преобразовать тип языка C++ в тип языка C или наоборот. Утилита gmmproc получает эту информацию из файла преобразования с расширением .m4, находящегося в вашей директории tools/m4/. Эта информация позволяет вызвать функцию языка C с помощью метода языка C++, передавая соответствующие параметры данной функции языка C. Например, данный макрос сообщает утилите gmmproc о том, как преобразовать указатель типа GtkTreeView в указатель типа Gtk::TreeView:
_CONVERSION(`GtkTreeView*',`TreeView*',`Glib::wrap($3)')
Строка "$3" будет заменена на имя параметра в момент, когда этот макрос преобразования будет обработан утилитой gmmproc.
.m4 из исходного кода gtkmm. Некоторые из упомянутых макросов:
_CONVERSION(`PrintSettings&',`GtkPrintSettings*',__FR2P) _CONVERSION(`const PrintSettings&',`GtkPrintSettings*',__FCR2P) _CONVERSION(`const Glib::RefPtr<Printer>&',`GtkPrinter*',__CONVERT_REFPTR_TO_P($3))
G.3.2. Инициализации с использованием файлов преобразований с расширением .m4
При создании оберток для методов сохранение возвращаемого функцией языка C значения в рамках так называемого выходного параметра обычно является желательным. В таком случае метод языка C++ не возвращает значения, но выходной параметр, с помощью которого сохраняется возвращаемое функцией языка C значение, добавляется в список аргументов метода языка C++. Утилита gmmproc позволяет реализовывать такой механизм, но в любом случае необходим соответствующий макрос инициализации, который сообщит gmmproc о том, как следует инициализировать параметр языка C++, используемый для сохранения возвращаемого функцией языка C значения.
GtkWidget* и по какой-либо причине вместо метода языка C++, который возвращает объект виджета, желательно создать метод языка С++, который будет возвращать объект виджета с помощью указанного параметра, потребуется аналогичный приведенному ниже макрос инициализации:
_INITIALIZATION(`Gtk::Widget&',`GtkWidget*',`$3 = Glib::wrap($4)')
Строка "$3" будет заменена на имя выходного параметра метода C++, а строка "$4" - на возвращаемое значение функции языка C в момент обработки данного макроса с помощью утилиты gmmproc. Для удобства строка "$1" также заменяется на тип языка C++ без амперсанта (&), а строка "$2" - на тип языка C.
G.3.3. Макрос класса
Макрос класса описывает сам класс, а также способ его взаимодействия с лежащим в основе типом языка C. Он позволяет генерировать некоторые внутренние конструкторы, методы gobject_, объявления типов с использованием оператора typedef, методы доступа gobj(), производить регистрацию типов, а также генерировать реализацию метода Glib::wrap() помимо других вещей.
Другие макросы, такие, как _WRAP_METHOD() и _WRAP_SIGNAL() могут использоваться исключительно после использования макроса _CLASS_*.
G.3.3.1. _CLASS_GOBJECT
GObject, причем класс этой обертки не наследуется от класса Gtk::Object.
_CLASS_GOBJECT_CLASS_GOBJECT( класс языка C++, класс языка C, макрос преобразования языка C, базовый класс языка C++, базовый класс языка C )
accelgroup.hg:
_CLASS_GOBJECT(AccelGroup, GtkAccelGroup, GTK_ACCEL_GROUP, Glib::Object, GObject)
G.3.3.2. _CLASS_GTKOBJECT
Gtk::Object, как класс виджета или диалога.
_CLASS_GTKOBJECT( класс языка C++, класс языка C, макрос преобразования языка C, базовый класс языка C++, базовый класс языка C )
button.hg:
_CLASS_GTKOBJECT(Button, GtkButton, GTK_BUTTON, Gtk::Bin, GtkBin)
Обычно вы будете использовать данный макрос в том случае, если класс уже унаследован от класса Gtk::Object. Например, вы будете использовать его при создании обертки для виджета из состава GTK+, так как класс Gtk::Widget наследуется от класса Gtk::Object.
Вы также можете наследовать классы, не имеющие отношения к виджетам, от класса Gtk::Object, причем в этом случае они смогут использоваться без умного указателя типа Glib::RefPtr. К примеру, экземпляры данных классов могут создаваться с помощью метода Gtk::manage() или в стеке с использованием переменной класса. Работать с подобными объектами достаточно удобно, но вы должны использовать описанный подход только тогда, когда уверены в том, что реальный подсчет ссылок не требуется. Мы считаем данный подход полезным для работы с виджетами.
G.3.3.3. _CLASS_BOXEDTYPE
GObject и регистрируемой с помощью функции g_boxed_type_register_static().
_CLASS_BOXEDTYPE( класс языка C++, класс языка C, функция создания, функция копирования, функция освобождения зарезервированной для хранения памяти )
Gdk::RGBA:
_CLASS_BOXEDTYPE(RGBA, GdkRGBA, NONE, gdk_rgba_copy, gdk_rgba_free)
G.3.3.4. _CLASS_BOXEDTYPE_STATIC
GdkRectangle. Он аналогичен макросу _CLASS_BOXEDTYPE, но в данном случае структура языка C не создается динамически.
_CLASS_BOXEDTYPE_STATIC( класс языка C++, класс языка C )
Gdk::Rectangle:
_CLASS_BOXEDTYPE_STATIC(Rectangle, GdkRectangle)
G.3.3.5. _CLASS_OPAQUE_COPYABLE
_CLASS_OPAQUE_COPYABLE( класс языка C++, класс языка C, функция создания, функция копирования, функция освобождения зарезервированной для хранения памяти )
Gdk::Checksum:
_CLASS_OPAQUE_COPYABLE(Checksum, GChecksum, NONE, g_checksum_copy, g_checksum_free)
G.3.3.6. _CLASS_OPAQUE_REFCOUNTED
Glib::RefPtr.
_CLASS_OPAQUE_REFCOUNTED( класс языка C++, класс языка C, функция создания структуры, функция создания ссылки, функция удаления ссылки )
Pango::Coverage:
_CLASS_OPAQUE_REFCOUNTED(Coverage, PangoCoverage, pango_coverage_new, pango_coverage_ref, pango_coverage_unref)
G.3.3.7. _CLASS_GENERIC
_CLASS_GENERIC( класс языка C++, класс языка C )
Pango::AttrIter:
_CLASS_GENERIC(AttrIter, PangoAttrIterator)
G.3.3.8. _CLASS_INTERFACE
GTypeInterface.
_CLASS_INTERFACE( класс языка C++, класс языка C, макрос преобразования языка C, структура интерфейса языка C, базовый класс языка C++ (необязательно), базовый класс языка C (необязательно) )
celleditable.hg:
_CLASS_INTERFACE(CellEditable, GtkCellEditable, GTK_CELL_EDITABLE, GtkCellEditableIface)
Два последних параметра являются необязательными и предназначены для тех случаев, когда описываемый интерфейс наследуется от другого интерфейса, что происходит тогда, когда класс на основе класса GInterface наследуется от другого класса на основе класса GInterface.
loadableicon.hg:
_CLASS_INTERFACE(LoadableIcon, GLoadableIcon, G_LOADABLE_ICON, GLoadableIconIface, Icon, Gicon)
G.3.4. Макросы конструктора
Макросы _CTOR_DEFAULT() и _WRAP_CTOR() добавляют конструкторы, создавая обертки над указанным функциями *_new() языка C. Эти макросы предполагают, что объект языка C имеет свойства с теми же именами, что и параметры функции, как обычно и бывает, поэтому он может непосредственно передавать параметры функции g_object_new(). Эти конструкторы на самом деле никогда не вызывают функции *_new() языка C, так как в реальности gtkmm приходится создавать экземпляры классов, соответствующих унаследованным от типа GType типам, а функции *_new() языка C являются всего лишь вспомогательными функциями для разработчиков, использующих язык программирования C.
_CLASS_GOBJECT() конструкторы должны быть объявлены как защищенные (protected) (а не как публичные (public)) члены класса, причем каждый конструктор должен иметь соответствующий макрос _WRAP_CREATE() в секции для публичных объявлений. Такой подход предотвращает создание экземпляра класса без использования умного указателя типа Glib::RefPtr. Пример такого объявления:
class TextMark : public Glib::Object
{
_CLASS_GOBJECT(TextMark, GtkTextMark, GTK_TEXT_MARK, Glib::Object, GObject)
protected:
_WRAP_CTOR(TextMark(const Glib::ustring& name, bool left_gravity = true), gtk_text_mark_new)
public:
_WRAP_CREATE(const Glib::ustring& name, bool left_gravity = true)
G.3.4.1. _CTOR_DEFAULT
Данный макрос создает стандартный конструктор без аргументов.
G.3.4.2. _WRAP_CTOR
Данный макрос создает конструктор с аргументами, эквивалентный функции *_new() языка C. На самом деле этот макрос не будет использовать функцию *_new(), а просто создаст эквивалентный конструктор с такими же типами аргументов. Он принимает описание конструктора языка C++ и имя функции языка C.
- errthrow
- Данный аргумент сообщает утилите
gmmprocо том, что функция*_new()языка C имеет последний параметр типаGError**, который должен игнорироваться.
G.3.4.3. Создание конструкторов вручную
*_new() языка C в точности не соответствуют свойствам объекта или тогда, когда функция *_new() языка C выполняет дополнительные действия помимо вызова функции g_object_new(), в файле с расширением .ccg также может быть использован макрос _CONSTRUCT() для сокращения объема работы. Макрос _CONSTRUCT принимает наборы имен свойств и значений. Пример из файла button.ccg:
Button::Button(const Glib::ustring& label, bool mnemonic)
:
_CONSTRUCT("label", label.c_str(), "use_underline", gboolean(mnemonic))
{}
Следующий раздел : Приложение G.3.5. Макросы методов.
