Ещё один “подход” к языку daScript от Gaijin. В последней заметке про использование байндингов к OpenGL в daScript, я упоминал про наличие скрипта dasClangBind, позволяюшего генерировать байндинги к библиотекам на C и C++. Так как из документации к скрипту только совет автора Use it, abuse it
, то неплохо попробовать его в деле, чтобы разобраться, что он умеет/не умеет.
С помощью этого генератора байндингов сделаны обёртки над: dasRequests, dasPhys2d, а также добавленные в основной репозиторий dasGLFW, dasBGFX, dasImgui, dasOpenGL, dasClangBind
(привязки для генератора байндингов тоже сгенерированы им самим).
dasClangBind
не собирается с дефолтными настройками cmake, поэтому сначала необходимо включить его сборку. В файле CMakeLists.txt видим настройку пути с libclang
:
Можно скачать скомпилированные библиотеки LLVM (yay, даже для windows!), и указать путь к скачанной библиотеке с cmake-файле. Дальше перегенерируем решение с помощью команды generate_msvc_XXX.bat
и компилируем проект libDasModuleClangBind
.
Получаем библиотеку libDasModuleClangBind.lib
, которую можно подключить для статической линковки из проекта, который будет использовать этот модуль (командой TARGET_LINK_LIBRARIES
). В сгенерированном решении убеждаемся в том, что линкер подключает библиотеки libDasModuleClangBind.lib
и libclang.lib
:
Далее в коде подключаем заголовочный файл и макрос добавления модуля в daScript:
Теперь в das-скрипте можно импортировать модуль cbind
, который предоставляет функции-обёртки над библиотекой clang
, а главное — cbind_boost
, классы, с помощью которых можно настроить поведение генераторы, без низкоуровневого обращения к c-апи clang-а:
libclang#
Для начала лучше бегло ознакомиться с тем, что умеет libclang
:
Using libclang to Parse C++
Пример разбора C++ кода с помощью libclang на Python
Choosing the Right Interface for Your Application
DasGenBind#
У генератор привязок dasClangBind
, есть 2 режима: генерация обёрток над функциями в виде daScript (с помощью ffi-интерфейса dasbind
) — DasGenBind
, и более мощная генерация “обвязочного” c++-кода библиотеки — CppGenBind
. С помощью DasGenBind
сгенерированы байндинги к OpenGL, так как сама библиотека language-agnostic, и её обвязки тривиальны — используются только функции и примитивные типы.
CppGenBind#
Более интересно посмотреть на байндинги к glfw, по которым можно приблизительно понять, что генерируется автоматически, а что необходимо добавлять в исключения и дописывать руками. dasClangBind
в ходе своей работы пишет, какие объявляния функций он пропускает (код - поиск по ключевому слову skip
):
- шаблоны
- функции с аргументами-указателями на функции (к примеру, колбеки)
- чисто виртуальные функции
- глобальные операторы
Также генерируются, но вызывают последующие ошибки компиляции, функции (в лучших традициях текстов ошибок шаблонов C++), получающие аргументы POD-типов по значению.
Для таких функций предполагается добавление их в список пропускаемых при автоматической генерации и последующее написания обработчика вручную:
Для дописывания несгенерированных автоматически функций предусмотрен файл MODULENAME.main.cpp
. На выходе генератор байндингов выдаёт пачку и кусок cmake-файла в stdout, с помощью которого можно собрать их в модуль. На практике почему-то у меня не создавались файлы MODULE.func.reg.inc
и MODULE.func.decl.,inc
, их для теста заполнил руками.
CmakeList.txt#
В качестве шаблона cmake-файла можно взять готовый из других модулей, основная логика:
- собрать модуль из сгенерированных файлов (это за нас выводит сам
dasClangBind
) - подключить lib-файл самой C++ библиотеки, для которой делается обвязка
- определить переменные сборки daScript, позволяющие отключить модуль по желанию пользователя
Генерация байндингов для библиотеке MessagePack#
Исходя из ограничений генератора, для учебного примера проще всего выбрать для примера максимально простую библиотеку, имеющую C, а не С++-интерфейс. Например - MessagePack.
Стартовый код генератора:
Такой скрипт генерирует привязки к библиотеке, однако при её компиляции возникают несколько ошибок вида:
Необходимо добавить эти функции в список исключаемых из генерации:
Убрав их из генерации, получаем компилирующийся модуль daScript dasMsgpack
.
Тестовый скрипт#
Попытаемся портировать тестовый пример библиотеки с MessagePack
с языка C на daScript:
Некоторые функции из примеры не попали в автоматическую обвязку, поэтому необходимо дописать обвязку для них вручную в файле msgpack.main.cpp
:
Теперь скрипт работает и выдаёт корректный результат десериализации объекта:
Дальнейшая работа над модулем может предполагать:
- возможность устанавливать daScript колбеки (пример из dasGlfw)
- daScript-обвязка над POD-структурой msgpack_object и корректная передача исключенных типов(?)
- написание “daScript-ивизирующей” обёртки msgpack_boost, для перехода от с-апи к более удобной работы с библиотекой