Библиотека сайта 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. Макросы методов.