Система плагинов KiCad

Авторские права © 2016 на данный документ принадлежит его разработчикам (соавторам), перечисленным ниже. Документ можно распространять и/или изменять в соответствии с правилами лицензии GNU General Public License (http://www.gnu.org/licenses/gpl.html), версии 3 или более поздней, или лицензии типа Creative Commons Attribution License (http://creativecommons.org/licenses/by/3.0/), версии 3.0 или более поздней.

Все торговые знаки этого руководства принадлежат его владельцам.

Соавторы

Cirilo Bernardo

Перевод

Барановский Константин <baranovskiykonstantin@gmail.com>, 2016-2019

Обратная связь

Оставить свои комментарии или замечания можно на следующих ресурсах:

Дата публикации

29 января 2016 года

1. Введение в систему плагинов KiCad

Система плагинов KiCad - это специальный механизм для расширения возможностей KiCad, использующий динамические библиотеки. Одно из основный преимуществ использования плагинов — это отсутствие необходимости заново собирать весь проект KiCad в процессе разработки плагина. На деле, плагины можно построить с применением очень малого набора заголовочных файлов из всего дерева исходного кода KiCad. Освобождение от необходимости сборки KiCad в процессе разработки, здорово увеличивает продуктивность благодаря тому, что разработчик компилирует только тот код, который непосредственно относится к проектируемому плагину, что, в свою очередь, уменьшает время на каждую сборку в процессе тестирования.

Изначально, система плагинов была разработана для реализации предварительного просмотра 3D-моделей и обеспечения поддержки большего количества форматов 3D-моделей, без необходимости вносить серьезные изменения в исходный код KiCad для каждого нового поддерживаемого формата. Механизм плагинов со временем был обобщен и, таким образом, в будущем разработчики смогут создавать плагины различных классов. На данный момент в KiCad реализованы только 3D-плагины, но планируется добавить класс плагинов для печатных плат, который позволит пользователям реализовать импорт и экспорт данных.

1.1. Классы плагинов

Плагины делятся на классы, так как каждый из них решает проблемы определённой области и, поэтому, требует отдельного интерфейса к данной области. Например, плагины 3D-моделей загружают трёхмерные данные из файлов и преобразуют их в формат, который может быть показан в программе 3D-просмотра, в то время как плагин импорта/экспорта печатных плат должен принимать данные о печатных платах и экспортировать их в другой формат электрических или механических данных для KiCad. На данный момент разработан только класс 3D-плагинов и именно на нём будет сосредоточено внимание в этом документе.

Для реализации нового класса плагина необходимо добавить код в дерево исходного кода KiCad, который будет управлять загрузкой плагина. В файле plugins/ldr/pluginldr.h, из исходного кода KiCad, определён базовый класс для всех загрузчиков плагинов. В этом классе определены общие функции, которые должны присутствовать в любом из плагинов KiCad (шаблонный код), а их реализация будет выполнять основные проверки на совместимость версий между загрузчиком и доступными плагинами. Заголовочный файл plugins/ldr/3d/pluginldr3d.h определяет загрузчик для класса 3D-плагинов. Загрузчик отвечает за загрузку полученного плагина и делает его функции доступными для KiCad. Каждый экземпляр загрузчика плагинов предоставляет реализацию конкретного плагина и выступает в качестве прозрачного моста между kicad и функциями плагина. Для поддержки плагинов нужно не только добавить код загрузчика в исходный код KiCad, ещё нужен код для обнаружения плагинов и код для вызова функций плагина через загрузчик. В случае с 3D-плагином, обнаружение и вызов функций, вместе, реализовано в классе S3D_CACHE.

Разработчикам плагина не нужно разбираться в деталях исходного кода KiCad для управления им, если новый класс плагинов уже разработан. Для реализации плагина нужно лишь определить функции, объявленные в соответствующем классе плагинов.

Заголовочный файл include/plugins/kicad_plugin.h объявляет основные функции, обязательные для всех плагинов KiCad. Эти функции определяют имя класса плагина и имя данного плагина, возвращают информацию о версии API класса, информацию о версии самого плагина и проверяют их на совместимость. Вкратце об этих функциях:

1.1.1. Класс плагинов PLUGIN_3D

В заголовочном файле include/plugins/3d/3d_plugin.h объявляются функции, которые должны быть реализованы в во всех 3D-плагинах, а также указано несколько функций, которые пользователь не должен изменять. Следующие функции не должны реализоваться пользователем:

Следующие функции должны быть реализованы пользователем:

2. Примеры: Класс 3D-плагинов

Этот раздел содержит описание двух очень простых плагинов из класса PLUGIN_3D и проведёт пользователя от настройки до сборки кода.

2.1. Простой 3D-плагин

Этот пример проведёт пользователя через весь процесс разработки очень простого 3D-плагина под именем "PLUGIN_3D_DEMO1". Цель этого примера — показать конструкцию элементарного 3D-плагина, который не делает ничего, кроме предоставления некоторых фильтров типов файлов, что позволит пользователям KiCad отфильтровать файлы в процессе выбора 3D-моделей. Показанный здесь код, является необходимым минимумом для любого 3D-плагина и может быть использован как шаблон для создания более функциональных плагинов.

В процессе сборки демонстрационного проекта понадобится следующее:

  • CMake

  • Заголовочные файлы плагина KiCad

  • Библиотека графа сцены KiCad (kicad_3dsg)

Для автоматического обнаружения заголовочных файлов KiCad и библиотеки нужно воспользоваться скриптом FindPackage на CMake. Скрипт, приведённый в этом примере, должен работать в Linux и MSWindows, если соответствующие заголовочные файлы установлены в ${KICAD_ROOT_DIR}/kicad, а библиотека графа сцены — в ${KICAD_ROOT_DIR}/lib.

Для начала создайте каталог для проекта и скрипт FindPackage:

KiCad и его заголовочные файлы для плагина должны быть установлены. Если они установлены в пользовательский каталог или в /opt в Linux, или используется Windows, то нужно определить переменную среды KICAD_ROOT_DIR, которая будет указывать на каталог kicad, содержащий каталоги include и lib. Для OSX, показанный здесь скрипт FindPackage, возможно, придётся немного подкорректировать.

Для настройки и сборки кода примера будет использоваться CMake, создайте файл скрипта CMakeLists.txt:

Первый демонстрационный проект очень прост. Он состоит из единственного файла без каких-либо внешних зависимостей (помимо зависимостей компилятора). Начнём с создания каталога для исходного кода:

Теперь создайте файл исходного кода для самого плагина:

s3d_plugin_demo1.cpp

Данный файл исходного кода содержит минимальный набор всех необходимых элементов для реализации 3D-плагина. Этот плагин не производит никаких данных для рендеринга моделей, но может дополнить KiCad списком поддерживаемых расширений файлов моделей и фильтров типов файлов в диалоговом окне выбора 3D-моделей. К тому же, в KiCad строка расширения используется для выбора плагинов, с помощью которых можно загрузить выбранные модели. Например, если выбрано расширение wrl, то KiCad будет вызывать каждый плагин, который объявил о поддержке этого расширения, до тех пор, пока один из них не вернёт данные визуализации. Фильтры файлов, предоставленные каждым из плагинов, передаются в диалоговое окно выбора 3D-моделей, чтобы улучшить процесс поиска.

Для сборки плагина:

Плагин будет построен, но не установлен. Можно скопировать его в какталог, в котором хранятся плагины, установленные вместе с kicad, если желаете, чтобы он был загружен.

2.2. Сложный 3D-плагин

Этот пример проведёт пользователя через весь процесс разработки 3D-плагина под именем "PLUGIN_3D_DEMO2". Цель этого примера — показать конструкцию элементарного графа сцены, который kicad сможет отобразить. Плагин должен поддерживать тип файлов txt. Кроме этого, данный файл должен существовать, чтобы менеджер кэша смог запустить плагин. Содержимое файла не обрабатывается плагином, вместо этого, он просто создаёт граф сцены, содержащий пару тетраэдров. В данном примере предполагается, что первый пример был завершен и файлы скриптов CMakeLists.txt и FindKICAD.cmake были созданы.

Поместите новый файл исходного кода в тот же каталог, в котором находится файл исходного кода из предыдущего примера, и дальше будет дополнен уже имеющийся файл CMakeLists.txt, чтобы построить этот пример. Так как данный плагин будет создавать граф сцены для KiCad, нужно подключить библиотеку графов сцены из KiCad — kicad_3dsg. Эта библиотека предоставляет набор классов, которые можно использовать для построения объекта графа сцены. Объект графа сцены — это вспомогательный формат данных визуализации, который используется менеджером кэша трехмерных данных (3D Cache Manager). Все плагины, поддерживающие модель визуализации должны преобразовывать данные моделей в граф сцены с помощью библиотеки.

Первым делом нужно дополнить CMakeLists.txt для сборки примера проекта:

Теперь перейдите в каталог с исходным кодом и создайте новый файл:

s3d_plugin_demo2.cpp

3. Интерфейс программирования приложений (API)

Плагины создаются путём реализации интерфейса программирования приложений (Application Programming Interface — API). Каждый класс плагинов имеет свой уникальный API и в приведённых примерах 3D-плагинов была показана реализация API для класса 3D-плагинов, согласно объявлениям из заголовочного файла 3d_plugin.h. Кроме того, плагины могут использовать дополнительный API, объявленный в исходном коде KiCad. В случае с 3D-плагинами, все те плагины, что поддерживают визуализацию моделей, должны взаимодействовать используя API графов сцены, который объявлен в заголовочном файле ifsg_all.h и вложенных в него.

В этом разделе описываются детали API доступных классов плагинов и других API из KiCad, которые могут потребоваться для реализации новых классов.

3.1. API класса плагинов

На данный момент доступен только один класс плагинов для KiCad — это класс 3D-плагинов. Все классы плагинов для KiCad должны реализовывать основной набор функций, объявленный в заголовочном файле kicad_plugin.h. Эти объявления можно рассматривать как базовый класс плагинов KiCad. Но на самом деле, реализации базового класса плагинов для KiCad не существует, эти заголовочные файлы присутствуют только для того, чтобы убедиться в том, что разработчики реализуют данные функции в каждом новом плагине.

В самом KiCad, каждый экземпляр загрузчика плагина реализует тот же API, что и плагин, так как этот загрузчик предоставляет все возможности данного класса. Это достигается тем, что класс загрузчика плагинов предоставляет открытый интерфейс, содержащий такие же имена функций, что и в реализации самого плагина. Список параметров может отличаться, чтобы можно было уведомить пользователя о возникновении каких-либо проблем, например, о том, что плагин не удалось загрузить. В процессе работы, загрузчик использует сохранённые указатели на каждую из функций API для их дальнейшего вызова по требованию пользователя.

3.1.1. API: базовый класс плагинов KiCad

Базовый класс плагинов KiCad определён в заголовочном файле kicad_plugin.h. Этот заголовочный файл должен подключаться ко всем другим классам плагинов. Для примера, посмотрите на объявления в заголовочном файле 3d_plugin.h для класса 3D-плагинов. Прототипы этих функций кратко описаны в разделе Классы плагинов. В pluginldr.cpp показано как реализуется API базового загрузчика.

Чтобы понять назначение обязательных функций из заголовочного файла базового класса плагинов, нужно рассмотреть, что происходит при загрузке этих плагинов. В классе загрузчика объявляется виртуальная функция Open(), в которую передаётся полный путь к загружаемому плагину. В реализации функции Open() каждого конкретного класса загрузчика вызывается защищенная (protected) функция open() из базового загрузчика. Эта базовая функция open() пытается найти адреса каждой из обязательных функций базового плагина. Как только адреса для каждой из функций будут получены, начнётся выполнение следующих проверок:

  1. Вызывается функция плагина GetKicadPluginClass() — возвращаемый результат сравнивается со значением из загрузчика для данного класса плагинов. Если значения не соответствуют, значит этот плагин не предназначен для работы с данным загрузчиком.

  2. Вызывается функция плагина GetClassVersion() — возвращается версия API класса плагина, реализованная данным плагином.

  3. Вызывается функция загрузчика GetLoaderVersion() — возвращается версия API класса плагина, реализованная данным загрузчиком.

  4. В версиях API, полученных от плагина и загрузчика, должен совпадать главный номер версии (Major Version number), иначе считается что плагин с загрузчиком не совместимы. Это самая простая проверка на соответствие версий и выполняется она базовым загрузчиком плагина.

  5. Вызывается функция плагина CheckClassVersion() — в функцию передаётся версия API класса плагинов, полученная от загрузчика. Если плагин поддерживает указанную версию — возвращается истина (true), подтверждая совместимость. В таком случае загрузчик создаёт строку PluginInfo путём объединения результатов двух функций GetKicadPluginName() и GetPluginVersion(), и затем, процесс загрузки плагина продолжается с помощью функции Open() загрузчика.

3.1.2. API: класс 3D-плагинов

Класс 3D-плагинов объявлен в заголовочном файле 3d_plugin.h. Помимо обязательных функций, в нем присутствуют дополнительные, их описание содержится в разделе Класс плагинов: PLUGIN_3D. Загрузчик для этого класса плагинов определён в pluginldr3d.cpp и помимо обязательных функций API, реализует следующие дополнительные общедоступные функции:

Необходимые функция из класса 3D-плагинов выявляются с помощью следующих функций:

В общем случае, пользователь должен выполнить следующее:

  1. Создать объект класса KICAD_PLUGIN_LDR_3D.

  2. Вызвать функцию Open( "/path/to/myplugin.so" ), чтобы открыть нужный плагин. Возвращаемое значение нужно проверять, чтобы убедиться в успешной загрузке плагина.

  3. Вызвать любую функцию из класса 3D-плагинов, обнаруженную в KICAD_PLUGIN_LDR_3D.

  4. Вызвать Close() чтобы закрыть (выгрузить) плагин.

  5. Удалить объект класса KICAD_PLUGIN_LDR_3D.

3.2. API калсса графа сцены

API класса графа сцены определён в заголовочном файле ifsg_all.h и вложенных в него. API содержит несколько дополнительных методов, объявленных в пространстве имён (namespace) S3D в файле ifsg_api.h и вспомогательных классов, объявленных в различных заголовочных файлах ifsg_*.h. Вспомогательные классы поддерживают основные форматы графов сцены, которые вместе образуют структуру графов, совместимую с VRML2.0. Заголовочные файлы, структуры, классы и их общедоступные функции рассмотрены далее:

sg_version.h
sg_types.h

Заголовочный файл sg_base.h состоит из объявлений основных типов данных, которые используются в классах графов сцены.

sg_base.h

Класс IFSG_NODE — базовый класс для всех узлов графа сцены. Все объекты графа сцены реализуют общедоступные функции этого класса, хотя не все они используются некоторыми объектами.

ifsg_node.h

IFSG_TRANSFORM подобен узлу Transform из VRML2.0. Он может содержать любое количество дочерних или связанных узлов IFSG_SHAPE и IFSG_TRANSFORM. Корректный граф сцены должен иметь только один объект IFSG_TRANSFORM в качестве корневого.

ifsg_transform.h

IFSG_SHAPE подобен узлу Shape из VRML2.0. Он должен содержать единственный дочерний узел FACESET или ссылку на него. Также, может содержать дочерний узел APPEARANCE или ссылку на него.

ifsg_shape.h

IFSG_APPEARANCE подобен узлу Appearance из VRML2.0, но на данный момент, он реализован в соответствии с узлом Appearance, содержащим узел Material.

ifsg_appearance.h

IFSG_FACESET подобен узлу Geometry из VRML2.0, который содержит узел IndexedFaceSet. Он должен состоять из одного дочернего узла COORDS или ссылки на него, одного дочернего узла COORDINDEX и одного дочернего узла NORMALS или ссылки на него. Дополнительно, он может содержать дочерний узел COLORS или ссылку на него. Элементарные функции операций над векторами предназначены помочь пользователям в связывании этих векторов с поверхностями. Далее указаны некоторые отличия от VRML2.0:

  1. Векторы всегда относятся к вершинам.

  2. Цвета всегда присваиваются вершинам.

  3. Набор индексов координат должен описывать только треугольные грани.

ifsg_faceset.h
ifsg_coords.h

IFSG_COORDINDEX подобен массиву coordIdx[] из VRML2.0, он он должен описывать только стороны треугольников и, таким образом, общее количество индексов должно быть кратным 3-м.

ifsg_coordindex.h

IFSG_NORMALS соответствует узлу Normals из VRML2.0.

ifsg_normals.h

IFSG_COLORS подобен массиву colors[] из VRML2.0.

ifsg_colors.h

Остальные функции API определены в ifsg_api.h и показаны далее:

ifsg_api.h

Примеры реального использования API графа сцены можно посмотреть в примере 3D-плагина DEMO2 и в исходных кодах KiCad — 3D-плагины для работы с файлами в форматах VRML1, VRML2 и X3D.