На волне интереса к языку D решил и я внести свой вклад в его популяризацию. Статья не для новичков, а больше для тех кто рассматривает D как второй язык. Известно, что на заре своего развития, языки программирования имеют небогатый набор библиотек и это часто не позволяет начинать писать на них что-то серьёзное. Надеюсь статья поможет кому-нибудь переступить этот барьер.
Ниже будут рассмотрены возможности утилиты dub, а так же подключение сторонних пакетов и библиотек написанных на C/C++ на примере замечательной библиотеки libev.
Утилита dub
Честно говоря, я до сих пор “плаваю” в опциях dmd, необходимых для компиляции и сборки приложения. Виной тому утилита dub, которая берет на себя все эти заботы и позволяет отложить изучение нюансов компиляции и сборки предложения на потом, когда это действительно станет необходимо. Кроме этого, эта полезная программка выполняет функции пакетного менеджера, обладая функционалом, аналогичным утилитам pip для python, npm для javascript и т.п.
Инициализация проекта
Для инициализации приложения с помощью утилиты dub надо создать каталог проекта, перейти в него и выполнить команду:
$ dub init
В результате будет создан файл dub.json, с помощью которого задается конфигурация и параметры сборки приложения. А также, подкаталог source, содержащий файл app.d с незамысловатым хелоуворлдом.
Сборка и/или запуск приложения производится этой же утилитой, запускаемой из корневого каталога проекта, то есть из каталога, содержащего файл dub.json
. Чтобы скомпилировать, собрать и запустить хелоуворлд из файла app.d
, достаточно выполнить команду dub
.
Подключение сторонних пакетов (библиотек)
В терминах языка, библиотеки сторонних разработчиков на D, распространяемые в виде исходных кодов, называются пакеты. Утилита dub
использует реестр пакетов, находящийся по следующему адресу. Использование библиотек, написанных с помощью C/C++ также возможно, но для этого необходимо подключение в проект специальных пакетов, называемых binding. Сама же библиотека должна быть установлена в системе. Например, libev, которая дальше будет задействована, устанавливается в debian подобных дистрибутивах linux следующим образом:
$ sudo apt-get install dev-libev
Для использования её в проекте на D нужен биндинг, который добрый человек уже сделал и разместил в выше названном реестре. Там же есть инструкция, какие изменения нужно внести в файл dub.json
для использования libev
в проекте. Все сводится к добавлению в раздел dependencies файла dub.json
имени пакета, версии и, по необходимости, некоторых других параметров.
При следующем выполнении команды dub
, все перечисленные в dependencies пакеты будут проверены и подгружены в случае их отсутствия.
Хелоуворлд с использованием libev
После выше описанных манипуляций проект готов к использованию фичей из libev
. Ниже приведен код, который следует поместить в файл app.d
, и если все прошло гладко, получим исполняемый файл, который будет радовать раз в секунду сообщением “Hello, World!” в консоле.
import std.stdio;
import deimos.ev;
void main()
{
ev_timer watcher;
extern(C) void cb_timer(ev_loop_t* loop, ev_timer* watcher, int revents) {
writeln("Hello, World!");
}
auto p_loop = ev_loop_new(EVFLAG_AUTO);
ev_timer_init(&watcher, &cb_timer, 1.0, 1.0);
ev_timer_start(p_loop, &watcher);
ev_run(p_loop, 0);
}
Что тут стоит отметить в плане использования сторонних библиотек в программах на D?
Во-первых, во второй строке подключается пакет-биндинг к libev
. Во-вторых, функция обратного вызова cb_timer
определена как extern(C)
. Фактически её вызов будет происходить из недр подключенной библиотеки, а она у нас написана на С. Следовательно, соглашение о вызове cb_timer
должно соответствовать вызову функций написанных на С.
Что можно сказать в целом, глядя на код? Не считая фичи языка D, позволившей определить cb_timer
в теле функции main
, код мало отличается от аналогичной программы на C. Это связано с тем, что пакеты-биндинги обычно содержат минимальную обвязку над вызовами функций из сишных библиотек. Часто для удобства делается еще один уровень обвязки, который предоставляет более читаемый код с использованием “синтаксического сахара” языка D. Например, аналогичный код мог бы выглядеть как-то так.
import std.stdio;
import hilevel.libev;
void main()
{
auto watcher = new TimerWatcher(1.0, 1.0, (revents) {
writeln("Hello, World!");
});
defaultEventLoop.start();
}
Кстати, код приведенный выше — реально существующий. Я попробовал сделать высокоуровневую обертку над libev
, используя параметризованный класс для вотчеров. Получилось вроде неплохо. Если это будет кому-то интересно — в следующей статье расскажу об этом.
PS: Неплохо бы было уже сделать подсветку синтаксиса D в редакторе хабратопиков.
Автор: Alesh