В случае notify_notification_show
мы сделали второй аргумент типа Void
, поскольку предполагаем, что все работает так, как ожидалось. Мы также связали функцию notify_notification_update
. Этот метод на самом деле не обязателен, но он поможет кое-что продемонстрировать позже в этом разделе, так что следите за обновлениями!
Тестирование привязок
Следующий вопрос, на который нам нужно ответить: куда нам следует поместить файл привязки? Идеальным решением было бы создать выделенный сегмент и потребовать его в качестве зависимости. Основное преимущество, которое это дает, заключается в том, что другие могут использовать их независимо от источника нашего приложения CLI. Однако для целей этой демонстрации мы просто добавим их в исходные файлы нашего приложения CLI.
Мы собираемся создать подкаталог lib_notify
, чтобы хотя бы обеспечить некоторое разделение организации между типами, связанными с привязками, и нашей реальной логикой. Это также облегчит переключение на выделенный сегмент, если мы решим сделать это позже. Давайте создадим новый файл “./lib_notify”
в файл
Поскольку сами привязки не зависят от нашего приложения CLI, мы можем протестировать их независимо. Мы можем сделать это, добавив следующие строки в наш файл привязки, запускающий его, и обязательно удалив этот тестовый код после его запуска:
LibNotify.notify_init "Transform"
notification = LibNotify.notify_notification_new "Hello",
"From Crystal!", nil
LibNotify.notify_notification_show notification, nil LibNotify.notify_uninit
Если все работает правильно, вы должны увидеть уведомление на рабочем столе с заголовком “Привет” и текстом “От Crystal!”. Мы передаем nil
аргументам, для которых не имеем значения. Это работает нормально, поскольку эти аргументы являются необязательными, и Crystal автоматически преобразует их в нулевой указатель. Однако это не сработало бы, если бы переменная представляла собой объединение Pointer
и Nil
. Работа с необработанными привязками функциональна, но не удобна для пользователя. Обычной практикой является определение стандартных типов Crystal, которые обертывают типы привязки C. Это позволяет скрыть внутренние компоненты библиотеки C за API, который более удобен для пользователя и его легче документировать. Давайте начнем с этого сейчас.
Абстрагирование привязок
Основываясь на логике C, которую мы использовали ранее, нам нужны следующие две основные абстракции:
• Лучший способ отправить уведомление, чтобы избежать необходимости вызывать методы init
и uninit
.
• Улучшен способ создания/редактирования уведомления, ожидающего отправки.
Чтобы обработать первую абстракцию, давайте создадим новый файл
require "./lib_notify"
class Transform::Notification
@notification : LibNotify::NotifyNotification*
getter summary : String
getter body : String
getter icon : String
def initialize(@summary : String, @body : String, @icon : String = "")
@notification = LibNotify.notify_notification_new @summary, @body, @icon
end
def summary=(@summary : String) : Nil
self.update
end
def body=(@body : String) : Nil
self.update
end
def icon=(@icon : String?) : Nil
self.update
end
def to_unsafe : LibNotify::NotifyNotification* @notification
end
private def update : Nil
LibNotify.notify_notification_update @notification, @summary, @body, @icon
end
end
По сути, этот класс представляет собой просто обертку вокруг указателя уведомления C. Мы определяем метод #to_unsafe
, который возвращает завернутый указатель, чтобы позволить предоставить экземпляр этого класса функциям C. В этом типе мы также будем использовать notify_notification_update
. Этот тип реализует установщики для каждого свойства уведомления, которые обновляют значение внутри типа-оболочки, а также обновляют значения структур C.