Использование в языке D сторонних библиотек

ProgrammingDesigning and refactoringD
Tutorial
На волне интереса к языку 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 libev-dev

Для использования её в проекте на 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 mercury.core;

void main()
{
    new TimerWatcher(1.0, 1.0, (revents) {
        writeln("Hello, World!");
    }).start();
    defaultEventLoop.start();
}

Кстати, код приведенный выше — реально существующий. Я попробовал сделать высокоуровневую обертку над libev, используя параметризованный класс для вотчеров. Получилось вроде неплохо. Если это будет кому-то интересно — в следующей статье расскажу об этом.

Upd: По использованию dub здесь есть неплохая статья, автор достаточно подробно описал основные возможности утилиты.

PS: Неплохо бы было уже сделать подсветку синтаксиса D в редакторе хабратопиков.
Tags:DdlanglibevdubD как второй языкиспользование сторонних библиотек
Hubs: Programming Designing and refactoring D
+16
6.8k 45
Comments 17

Popular right now

Профессия Product Manager
January 27, 2021108,500 ₽Нетология
Аналитика для руководителей
January 27, 202167,500 ₽Нетология
Product Manager IT-проектов
January 28, 202160,000 ₽OTUS
JavaScript Developer. Professional
January 28, 202170,000 ₽OTUS
Тренажер product-менеджера
January 28, 202128,500 ₽SkillFactory