Библиотека сайта 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.5. Макросы методов
G.3.5.1. _WRAP_METHOD
_WRAP_METHOD( описание метода языка C++, имя функции языка C)
entry.hg
:
_WRAP_METHOD(void set_text(const Glib::ustring& text), gtk_entry_set_text)
Приведенная выше функция языка C (т.е., gtk_entry_set_text
) описана более подробно в файле с расширением .defs
, при этом файлы преобразования convert*.m4
содержат информацию, необходимую для преобразования типов параметров языка C++ к типам параметров языка C. Данный макрос также генерирует комментарии для документации doxygen на основе информации из файлов файлов *_docs.xml
и *_docs_override.xml
.
- refreturn
- Установка дополнительной ссылки на возвращаемое значение в том случае, если функция языка C не устанавливает ссылки.
- errthrow
- Использование последнего параметра типа
GError**
функции языка C для генерации исключения. - deprecated
- Размещение сгенерированного кода внутри блоков условной компиляции
#ifdef
. Текст сообщения об устаревании метода может быть задан с помощью дополнительного параметра. - constversion
- Использование простого вызова версии той же функции, возвращающей непостоянное значение, вместо генерации практически дублирующегося кода.
- ifdef
- Размещение сгенерированного кода внутри блоков условной компиляции
#ifdef
. - slot_name
- Указание имени представленного слотом параметра метода в случае наличия такового. Оно позволяет утилите
gmmproc
генерировать код для копирования слота и передачи его с помощью последнего параметра функции языка C с именемuser_data
типаgpointer
. Аргументslot_callback
должен также использоваться для указания имени связывающей функции обратного вызова с целью его передачи функции языка C. - slot_callback
- Используется совместно с аргументом
slot_name
для указания имени связывающей функции обратного вызова, которая выполняет извлечение указателя на функцию из слота и вызов этой функции. Адрес данной функции обратного вызова также передается функции языка C, для которой создается обертка. - no_slot_copy
- Указание утилите
gmmproc
на то, что не следует передавать копию слота функции языка C в том случае, если метод использует слот. Вместо этого будет осуществляться передача самого слота. Имя представленного слотом параметра а также имя связывающей функции обратного вызова должны быть указаны с помощью аргументовslot_name
иslot_callback
соответственно.
- В том случае, если объекты используются посредством умного указателя типа
Glib::RefPtr
: следует передавать умный указатель типаGlib::RefPtr
как неизменную ссылку. Например,const Glib::RefPtr<Gtk::FileFilter>& filter
. - В том случае, если неизменные объекты используются посредством умного указателя типа
Glib::RefPtr
: если объект не должен изменяться с помощью функции, следует удостовериться в том, что объект объявлен как неизменный даже в том случае, если умный указатель типаGlib::RefPtr
уже объявлен как неизменная ссылка. Например,const Glib::RefPtr<const Gtk::FileFilter>& filter
. - Создание оберток для параметров в форме связанных списков типов
GList*
иGSList*
: во-первых, вы должны узнать тип объекта, на который указывает поле данных каждого из элементов списка, причем обычно этот тип указывается в документации к функции языка C. После этого для списка может быть подготовлена обертка на основе контейнера типаstd::vector
. Например,std::vector< Glib::RefPtr<Gdk::Pixbuf> >
. Вы также можете столкнуться с необходимостью указания свойств типа для установки способа преобразования типов языка C в типы языка C++. - Создание оберток для возвращаемых связанных списков типов
GList*
иGSList*
: вы должны узнать о том, следует ли освобождать зарезервированную для списка память, а также о том, следует ли освобождать память, использованную для хранения элементов списка, также обратившись к документации функции языка C. Воспользовавшись этой информацией, вы сможете выбрать режим владения (none (без владения), shallow (частичное владение) или deep (полное владение)) для правила преобразования m4, которое вы, скорее всего, должны будете разместить непосредственно в файле с расширением .hg, так как режим владения зависит от функции, а не от типа данных. Пример макроса:#m4 _CONVERSION(`GSList*',`std::vector<Widget*>',`Glib::SListHandler<Widget*>::slist_to_vector($3, Glib::OWNERSHIP_SHALLOW)')
G.3.5.2. _WRAP_METHOD_DOCS_ONLY
_WRAP_METHOD()
, но он генерирует исключительно документацию для метода языка C++, который является оберткой для функции языка C. Используйте его тогда, когда вам приходится вручную разрабатывать метод, но вы хотите использовать документацию, которая будет сгенерирована в случае генерации метода.
_WRAP_METHOD_DOCS_ONLY(имя функции языка C)
container.hg
:
_WRAP_METHOD_DOCS_ONLY(gtk_container_remove)
G.3.5.3. _IGNORE/_IGNORE_SIGNAL
gmmproc
будет выводить предупреждения в стандартный поток вывода при обработке каждой функции и каждого сигнала, для которых вы забыли создать обертки, гарантируя создание завершенной обертки для всего API. Но в том случае, если вы не хотите создавать обертки для каких-либо функций и сигналов или в том случае, если вы решите самостоятельно разработать некоторые методы, вы можете использовать макрос _IGNORE()
или _IGNORE_SIGNAL()
для предотвращения вывода предупреждений утилитой gmmproc
.
_IGNORE(имя функции 1 языка C, имя функции 2 языка C, и.т.д.) _IGNORE_SIGNAL(имя сигнала 1 языка C, имя сигнала 2 языка C, и.т.д.)
buttonbox.hg
:
_IGNORE(gtk_button_box_set_spacing, gtk_button_box_get_spacing)
G.3.5.4. _WRAP_SIGNAL
signal_clicked()
, который возвращает прокси-объект. Утилита gmmproc
использует файл с расширением .defs
для определения типов параметров функции сигнала для языка C, а также файлы преобразования с расширением .m4
для определения подходящих типов для преобразования.
_WRAP_SIGNAL( описание обработчика сигнала языка C++, имя сигнала языка C)
button.hg
:
_WRAP_SIGNAL(void clicked(),"clicked")
Для реализации сигналов обычно используются указатели на функции во внутренней структуре GTK, а также соответствующее значение перечисления и функция g_signal_new()
в файле с расширением .c
.
- no_default_handler
- Не генерировать виртуальный метод
on_something()
, позволяющий перекрыть стандартный обработчик сигналов. Используйте данный аргумент в том случае, когда добавление сигнала со стандартным обработчиком может привести к нарушению ABI из-за увеличения размера таблицы виртуальных функций класса. - custom_default_handler
- Генерировать описание виртуального метода
on_something()
в заголовочном файле с расширением.h
без генерации реализации в файле исходного кода с расширением.cc
. Используйте данный аргумент тогда, когда вам нужно создать реализацию стандартного обработчика сигнала вручную. - custom_c_callback
- Не генерировать функцию обратного вызова языка C для данного сигнала. Используйте данный аргумент тогда, когда вам нужно разработать функцию обратного вызова вручную.
- refreturn
- Установить дополнительную ссылку для возвращаемого виртуальным методом
on_something()
значения в том случае, если функция языка C не устанавливает ссылки. - ifdef
- Поместить сгенерированный код в блоки условной компиляции
#ifdef
.
G.3.3.5 _WRAP_PROPERTY
gmmproc
использует файл с расширением .defs
для установления типа данных языка C, а также файлы правил преобразования типов с расширением .m4
для установления соответствия между типами данных для преобразований.
_WRAP_PROPERTY(имя свойства языка C, тип данных языка C++)
button.hg
:
_WRAP_PROPERTY("label", Glib::ustring)
G.3.5.6. _WRAP_VFUNC
_WRAP_VFUNC( описание метода языка C++, имя функции языка C)
widget.hg
:
_WRAP_VFUNC(SizeRequestMode get_request_mode() const, get_request_mode)
Функция языка C (т.е., get_request_mode
) более подробно описана в файле *_vfuncs.defs
, а файлы *.m4
содержат необходимые правила преобразования типов параметров языка C++ к типам параметров языка C.
- refreturn
- Установить дополнительную ссылку для возвращаемого функцией
something_vfunc()
значения в том случае, если функция, использующаяся в качестве виртуальной функции языка C, не устанавливает ссылки. - refreturn_ctype
- Установить дополнительную ссылку для возвращаемого значения перекрытой функции
something_vfunc()
в рамках функции обратного вызова языка C в том случае, если вызывающая функция языка C ожидает ее для предоставления ссылки. - errthrow
- Использовать последний параметр типа
GError**
(если такой существует) функции, использующейся в качестве виртуальной функции языка C, для генерации исключения. - custom_vfunc
- Не генерировать объявление виртуальной функции в файле с расширением
.cc
. Используйте данный аргумент в том случае, если вам нужно разработать виртуальную функцию вручную. - custom_vfunc_callback
- Не генерировать функцию обратного вызова языка C для виртуальной функции. Используйте данный аргумент в том случае, если вам нужно разработать функцию обратного вызова вручную.
- ifdef
- Разместить сгенерированный код в блоках условной компиляции
#ifdef
. - slot_name
- Указание имени представленного слотом параметра метода в случае наличия такового. Оно позволяет утилите
gmmproc
генерировать код для копирования слота и передачи его с помощью последнего параметра функции языка C с именемuser_data
типаgpointer
. Аргументslot_callback
должен также использоваться для указания имени связывающей функции обратного вызова с целью его передачи функции языка C. - slot_callback
- Используется совместно с аргументом
slot_name
для указания имени связывающей функции обратного вызова, которая выполняет извлечение указателя на функцию из слота и вызов этой функции. Адрес данной функции обратного вызова также передается функции языка C, для которой создается обертка. - no_slot_copy
- Указание утилите
gmmproc
на то, что не следует передавать копию слота функции языка C в том случае, если метод использует слот. Вместо этого будет осуществляться передача самого слота. Имя представленного слотом параметра а также имя связывающей функции обратного вызова должны быть указаны с помощью аргументовslot_name
иslot_callback
соответственно.
Правило, у которого могут быть исключения: если функция, выступающая в качестве виртуальной функции языка C, возвращает указатель на объект на основе GObject, т.е., на объект с подсчетом ссылок, виртуальная функция языка C++ должна возвращать объект типа Glib::RefPtr<>
. При этом необходимо использовать один из следующих дополнительных аргументов макроса: либо refreturn
, либо refreturn_ctype
.
G.3.6. Другие макросы
G.3.6.1. _IMPLEMENTS_INTERFACE
_IMPLEMENTS_INTERFACE(имя интерфейса языка C++)
button.hg
:
_IMPLEMENTS_INTERFACE(Activatable)
- ifdef
- Разместить сгенерированный код с блоках условной компиляции
#ifdef
.
G.3.6.2. _WRAP_ENUM
Данный макрос генерирует перечисление языка C++, являющееся оберткой для перечисления языка C. Вы должны указать желаемое имя перечисления языка C++, а также имя лежащего в его основе перечисления языка C.
enums.hg
:
_WRAP_ENUM(WindowType, GtkWindowType)
В том случае, если перечисление не относится к типу GType
системы типов, вы должны передать третий параметр NO_GTYPE
. Это именно тот случай, когда для перечисления языка C не реализована функция *_get_type()
, поэтому следует проявлять осторожность и не подключать дополнительный заголовочный файл для этой функции. Вам также следует отправить сообщение об ошибке в API языка C, так как все перечисления должны быть зарегистрированы в системе типов и иметь тип GType
.
icontheme.hg
:
_WRAP_ENUM(IconLookupFlags, GtkIconLookupFlags, NO_GTYPE)
G.3.6.3. _WRAP_ENUM_DOCS_ONLY
Данный макрос генерирует блок документации Doxygen для рассматриваемого перечисления. Он полезен при работе с перечислениями, обертки для которых не могут быть созданы с помощью макроса _WRAP_ENUM()
ввиду их сложного объявления (возможно, с использованием макросов языка C), но добавление сгенерированной документации для перечисления все же желательно. Данный макрос использует такой же синтаксис, как и макрос _WRAP_ENUM()
и принимает те же параметры (хотя аргумент NO_GTYPE
просто игнорируется из-за того, что регистрация в системе типов не оказывает влияния на генерацию документации перечисления).
G.3.6.4. _WRAP_GERROR
Данный макрос генерирует класс исключения языка C++, унаследованный от класса Glib::Error
с перечислением Code
и методом code()
. Вы должны указать желаемое имя класса языка C++, имя соответствующего перечисления языка C и префикс для значений перечисления языка C.
Это исключение впоследствии может генерироваться методами, которые были сгенерированы с помощью макроса _WRAP_METHOD()
с аргументом errthrow
.
pixbuf.hg
:
_WRAP_GERROR(PixbufError, GdkPixbufError, GDK_PIXBUF_ERROR)
G.3.6.5. _MEMBER_GET / _MEMBER_SET
_MEMBER_GET(имя поля языка C++, имя поля языка C, тип поля языка C++, тип поля зыка C) _MEMBER_SET(имя поля языка C++, имя поля языка C, тип поля зыка C++, тип поля языка C)
rectangle.hg
:
_MEMBER_GET(x, x, int, int)
G.3.6.6. _MEMBER_GET_PTR / _MEMBER_SET_PTR
_MEMBER_GET_PTR(имя поля языка C++, имя поля языка C, тип поля языка C++, тип поля языка C) _MEMBER_SET_PTR(имя поля языка C++, имя поля языка C, тип поля языка C++, тип поля языка C)
Pango::Analysis
из файла item.hg
:
// _MEMBER_GET_PTR(engine_lang, lang_engine, EngineLang*, PangoEngineLang*) // Это всего лишь комментарий. На самом деле сложно найти реальный пример использования данного макроса.
G.3.6.7. _MEMBER_GET_GOBJECT / _MEMBER_SET_GOBJECT
GObject
, на которые должны устанавливаться ссылки перед получением.
_MEMBER_GET_GOBJECT(имя поля языка C++, имя поля языка C, тип поля языка C++, тип поля языка C) _MEMBER_SET_GOBJECT(имя поля языка C++, имя поля языка C, тип поля языка C++, тип поля языка C)
Pangomm
из файла layoutline.hg
:
_MEMBER_GET_GOBJECT(layout, layout, Pango::Layout, PangoLayout*)
G.3.7. Обработка параметров утилитой gmmproc
Утилита gmmproc
может обрабатывать параметры объявлений методов в макросах, которые принимают объявления методов (таких, как _WRAP_METHOD()
, _WRAP_CTOR()
и _WRAP_CREATE()
) различными способами.
G.3.7.1. Изменение порядка следования параметров
Gtk::Widget
языка C++:
void gtk_widget_set_device_events(GtkWidget* widget, GdkDevice* device, GdkEventMask events);
_WRAP_METHOD(void set_device_events(Gdk::EventMask events{events}, const Glib::RefPtr<const Gdk::Device>& device{device}), gtk_widget_set_device_events)
_WRAP_METHOD(void set_device_events(Gdk::EventMask events{.}, const Glib::RefPtr<const Gdk::Device>& device{.}), gtk_widget_set_device_events)
Пожалуйста учтите, что при изменении порядка следования параметров описания метода в макросе _WRAP_SIGNAL() имена параметров языка C всегда должны быть p0 , p1 , и.т.д., так как утилита generate_extra_defs использует такие имена параметров вне зависимости от того, какие имена параметров могут использоваться в API языка C. На данный момент упомянутая утилита работает именно так. |
G.3.7.2. Обработка дополнительных параметров
_WRAP_SIGNAL()
и _WRAP_VFUNC()
имеется возможность сделать параметры необязательными, что приведет к генерации дополнительных методов языка C++ без каждого из указанных необязательных параметров. Например, предположим, что конструктор класса Gtk::ToolButton
является оберткой для следующей функции *_new()
:
GtkToolItem* gtk_tool_button_new(GtkWidget* icon_widget, const gchar* label);
NULL
для параметра label
, поэтому данный параметр является необязательным. Утилита gmmproc
должна генерировать оригинальный конструктор (со всеми параметрами) наряду с дополнительным конструктором, не использующим данный параметр, после добавления директивы {?}
к имени необязательного параметра таким образом, как показано ниже:
_WRAP_CTOR(ToolButton(Widget& icon_widget, const Glib::ustring& label{?}), gtk_tool_button_new)
В данном случае будут сгенерированы два конструктора: один конструктор с дополнительным параметром и один конструктор без него.
G.3.7.3. Обработка выходных параметров
_WRAP_METHOD()
имеется возможность передачи возвращаемого функцией языка C значения (если оно возвращается) посредством выходного параметра метода языка C++ вместо возврата методом языка C++ значения аналогично функции языка C. Для этого следует просто включить выходной параметр в список параметров метода языка C++ и добавить директиву {OUT}
к имени этого параметра. Например, в том случае, если функция gtk_widget_get_request_mode()
объявлена следующим образом:
GtkSizeRequestMode gtk_widget_get_request_mode(GtkWidget* widget);
SizeRequestMode
, может быть применен аналогичный следующему макрос:
_WRAP_METHOD(void get_request_mode(SizeRequestMode& mode{OUT}) const, gtk_widget_get_request_mode)
{OUT}
, добавленный к имени выходного параметра mode
, сообщает утилите gmmproc
о том, что следует поместить возвращаемое функцией языка С значение в этот выходной параметр. В данном случае, однако, также должен быть использован необходимый макрос инициализации, аналогичный следующему:
_INITIALIZATION(`SizeRequestMode&',`GtkSizeRequestMode',`$3 = (SizeRequestMode)($4)')
_INITIALIZATION(`SizeRequestMode&',`GtkSizeRequestMode',`$3 = ($1)($4)')
_WRAP_METHOD()
также позволяет использовать в методах языка C++ выходные параметры, связанные с выходными параметрами функций языка C, разумеется, в тех случаях, когда функции языка C имеют такие параметры. Например, предположим, что мы хотим создать обертку для следующей функции языка C, возвращающей значение с помощью выходного параметра rect
:
gboolean gtk_icon_view_get_cell_rect(GtkIconView* icon_view, GtkTreePath* path, GtkCellRenderer* cell, GdkRectangle* rect);
gmmproc
разместила возвращенное значение в выходном параметре rect
метода языка C++, должна быть использована аналогичная следующей форма записи директивы в рамках макроса _WRAP_METHOD()
:
_WRAP_METHOD(bool get_cell_rect(const TreeModel::Path& path, const CellRenderer& cell, Gdk::Rectangle& rect{>>}) const, gtk_icon_view_get_cell_rect)
{>>}
после имени параметра rect
указывает на то, что значение выходного параметра языка C++ должно быть установлено на основе значения, возвращенного с помощью параметра функции языка C. Утилита gmmproc
сгенерирует объявление временной переменной, в которой будет храниться значение, преданное с помощью выходного параметра, а также код для установки значения выходного параметра метода языка C++ на основе значения временной переменной. В этом случае может оказаться необходимым макрос инициализации _INITIALIZATION()
, описывающий метод получения типа Gdk::Rectangle&
из типа GdkRectangle*
и аналогичный следующему макросу:
_INITIALIZATION(`Gdk::Rectangle&',`GdkRectangle', `$3 = Glib::wrap(&($4))')
G.3.8. Базовые типы данных
Некоторые из базовых типов данных, используемых в рамках API языка C, имеют лучшие альтернативы в рамках языка C++. Например, нет необходимости в использовании логического типа данных gboolean
, так как язык C++ предлагает аналогичный тип данных bool
. В списке ниже представлены некоторые часто используемые в рамках API языка С типы данных, а также те типы данных, в которые вы можете преобразовать их для использования в рамках обертки библиотеки для языка C++.
Эквиваленты базовых типов данных
Тип данных языка C: gboolean
Тип данных языка C++: bool
Тип данных языка C: gint
Тип данных языка C++: int
Тип данных языка C: guint
Тип данных языка C++: guint
Тип данных языка C: gdouble
Тип данных языка C++: double
Тип данных языка C: gunichar
Тип данных языка C++: gunichar
Тип данных языка C: gchar *
Тип данных языка C++: Glib::ustring
(или std::string
для имен файлов)
Следующий раздел : Приложение G.4. Создаваемые вручную файлы исходного кода.