Введение
RubyCocoa — это фреймворк для macOS, обеспечивающий мост между языками программирования Ruby и Objective-C, позволяя пользователю управлять объектами Objective-C из Ruby и наоборот. Это позволяет создавать приложения Cocoa целиком на Ruby, а также приложения, сочетающие код Ruby и Objective-C. В 2008 году компания Apple разрабатывала проект MacRuby, призванный заменить RubyCocoa. Впоследствии, в 2012 году, была выпущена проприетарная разработка RubyMotion, доступная для iOS, macOS и Android. К полезным областям применения RubyCocoa относятся исследование возможностей объектов Cocoa в интерактивном режиме с помощью IRB, прототипирование приложений Cocoa, создание приложений Cocoa, объединяющих возможности Ruby и Objective-C, а также создание обертки для нативного графического интерфейса macOS для Ruby-скриптов. RubyCocoa является свободным программным обеспечением, распространяемым под лицензиями Ruby и LGPL.
RubyCocoa is a macOS framework that provides a bridge between the Ruby and the Objective C programming languages, allowing the user to manipulate Objective C objects from Ruby, and vice versa. It makes it possible to write a Cocoa application completely in Ruby as well as to write an application that mixes Ruby and Objective C code. An Apple project called MacRuby was under development to replace RubyCocoa in 2008. A proprietary spin off called RubyMotion was subsequently released in 2012, available for iOS, macOS and Android. Some useful applications of RubyCocoa are exploration of a Cocoa object's features with irb interactively, prototyping of a Cocoa application, writing a Cocoa application that combines the features of Ruby and Objective C and wrapping macOS' native GUI for a Ruby script. RubyCocoa is free software, released under both the Ruby License and the LGPL.
История
RubyCocoa была основана в 2001 году Хисакуни Фудзимото, когда он реализовал модуль расширения Ruby для обертывания функций NSObject и NSClassFromString. Позже она была интегрирована с Project Builder (который впоследствии стал Xcode). В 2002 году проект был зарегистрирован на SourceForge, и команда разработчиков начала расширяться. В 2006 году к списку разработчиков впервые присоединился сотрудник Apple, Лоран Сансонетти, а затем на WWDC была представлена RubyCocoa. Apple объявила, что RubyCocoa будет включена и поддерживаться в Mac OS X v10.5 “Leopard”. В августе 2008 года Сансонетти подтвердил, что MacRuby "должна заменить RubyCocoa" в будущем.
Как работает мост?
RubyCocoa иногда ошибочно воспринимается как набор привязок к Cocoa, что неверно. RubyCocoa — это реальный мост между языками программирования Objective-C и Ruby.
Импорт "Лейси-класса"
RubyCocoa будет импортировать классы Objective-C в мир Ruby по мере необходимости. Например, когда вы впервые обращаетесь к OSX::NSTableView в вашем коде, RubyCocoa извлечет всю необходимую информацию об этом классе из среды выполнения Objective-C и создаст класс Ruby с тем же именем, который будет выступать в качестве прокси. Он также импортирует таким же образом все производные классы.
Передача сообщений
Как уже было сказано ранее, RubyCocoa создает специальные прокси-объекты. Каждый раз, когда вы отправляете Ruby-сообщение прокси-объекту, RubyCocoa пытается перенаправить его встроенному экземпляру Objective-C, преобразуя имя сообщения в селектор Objective-C и обращаясь к среде выполнения Objective-C с просьбой о перенаправлении. Если в мире Objective-C возникает исключение, RubyCocoa преобразует его в исключение Ruby и передает вам. RubyCocoa использует библиотеку libffi для вызова реализаций методов Objective-C.
Автоматический метод
RubyCocoa позволяет легко переопределить метод Objective-C из Ruby, либо в подклассе, либо непосредственно в классе (как это делается в Objective-C с помощью категории). После вставки вашего метода, RubyCocoa извлекает сигнатуру существующего метода Objective-C и внедряет новую в среду выполнения Objective-C, с той же сигнатурой, но уже указывающую на ваш код. Для этого RubyCocoa использует библиотеку libffi для динамического создания замыкания, которое будет вызывать метод Ruby, и просто передает указатель на это новое замыкание в среду выполнения Objective-C.
Доступ к битам C
В силу особенностей языка Objective-C, вы можете свободно использовать C в коде Objective-C. Для обеспечения взаимодействия с соответствующими C-компонентами фреймворка Objective-C, такими как структуры C, функции, перечисления, константы и прочее, RubyCocoa использует проект BridgeSupport. RubyCocoa интерпретирует файлы BridgeSupport во время выполнения (с помощью очень быстрого xmlTextReader из libXML2) и соответствующим образом обрабатывает их содержимое. В частности, он создает Ruby-прокси-классы для структур C и генерирует функции. Следует отметить, что ресурсоемкие операции, такие как разрешение символов, выполняются по требованию и, очевидно, только один раз.
Форматирование строк
RubyCocoa способен обнаруживать API, использующие строки форматирования, такие как NSLog или NSString. stringWithFormat, и корректно преобразовывать переменные аргументы в типы, указанные в строке форматирования.
Показатели функций
RubyCocoa позволяет передавать объекты Ruby Proc в качестве аргументов, ожидающих указатели на функции. Затем он использует библиотеку libffi для динамического создания замыкания и передачи его в базовую функцию или метод.
Создание приложений Cocoa на языке Ruby
Установка RubyCocoa также автоматически устанавливает соответствующие шаблоны Xcode. Это позволяет разработчикам выбирать тип проекта Xcode "Cocoa Ruby Application", и Xcode сгенерирует все необходимые файлы.
Преимущества RubyCocoa
Поскольку Ruby — интерпретируемый язык, нет необходимости часто перекомпилировать приложение в процессе разработки. Некоторые из богатых возможностей Ruby, такие как встроенная поддержка регулярных выражений, позволяют быстрее писать код и делают RubyCocoa идеальным инструментом для прототипирования.
Недостатки
Не обращая внимания на скорость интерпретатора Ruby, приложения RubyCocoa всегда будут работать медленнее, чем приложения Objective C/Cocoa из-за дополнительных накладных расходов на преобразование объектов. Поскольку Ruby не является потокобезопасным, невозможно запустить несколько нативных потоков для выполнения кода RubyCocoa. Однако можно использовать эмулированные потоки Ruby.