Найти в Дзене
Разработка на 1С

Конструктор внешних компонент 1C (native API)

В статье описывается приложение-конструктор внешних компонент (native API). Конструктор упрощает процесс разработки за счет удобного добавления всех нужных функций и процедур в графическом режиме, с указанием их параметров и типов параметров. На выходе приложение генерирует готовый код на С++ и Rust и позволяет сразу приступить к реализации, без настройку API компоненты вручную. Так же конструктор автоматизирует интеграцию библиотек на Rust в компоненту на С++. Таким образом на С++ будет описана только базовая логика взаимодействия компоненты и платформы, а вся основная логика будет реализована в библиотеке на Rust. Этот подход выбран так как реализовать native API на С++ проще и так же взаимодействовать с библиотекой на Rust через FFI интерфейс не сложно и мало отличается от обычного вызова методов из той же программы на С++. Я думаю общая идея понятна, перейду к примерам. Используя конструктор, создам внешнюю компоненту и несколько методов. Первый простой пример, для демонстрации общ

В статье описывается приложение-конструктор внешних компонент (native API). Конструктор упрощает процесс разработки за счет удобного добавления всех нужных функций и процедур в графическом режиме, с указанием их параметров и типов параметров. На выходе приложение генерирует готовый код на С++ и Rust и позволяет сразу приступить к реализации, без настройку API компоненты вручную.

Так же конструктор автоматизирует интеграцию библиотек на Rust в компоненту на С++. Таким образом на С++ будет описана только базовая логика взаимодействия компоненты и платформы, а вся основная логика будет реализована в библиотеке на Rust. Этот подход выбран так как реализовать native API на С++ проще и так же взаимодействовать с библиотекой на Rust через FFI интерфейс не сложно и мало отличается от обычного вызова методов из той же программы на С++.

Я думаю общая идея понятна, перейду к примерам.

Используя конструктор, создам внешнюю компоненту и несколько методов.

Первый простой пример, для демонстрации общего принципа работы конструктора.

Добавлю функцию, которая просто будет возвращать строку из метода на rust.

Запущу конструктор (это приложение разработанное на tauri)

Окно приложения

На закладке Функции добавлю новую функцию

-2

Укажу русский и английский синоним для функции. Параметров у нее не будет, поэтому таблица Параметры пустая. По умолчанию установлен флаг "Вызов Rust метода". В случае установки этого флага буде создан весь необходимый код для взамодействия с Rust:
- Будут созданы заголовочные файлы  с описанием сигнатур функций на Rust;

- Будет создание код на С++ который вызывает метод Rust;

- Реализовано освобождение памяти после того как С++ код прочитает значение которое вернут Rust (общение между С++ и Rust происходит через указатели, поэтому нужно освобождать память);

- На стороне Rust будут так же созданы соответствующие методы.

Так как добавляется функция, автоматически установлен флаг "Возвращает значение".

И нажму "Save".

Настройки готовы, теперь можно сгенерировать код.

Для этого на закладке "Сборка" нажму кнопку "Собрать".

-3

После чего в каталоге где расположена программа, будет создан каталог с исходным кодом компоненты "new component".

Этот каталог содержит код на С++ и Rust

-4

Теперь нужно собрать внешнюю компоненту. Так как библиотека на Rust статическая и включается в динамическую библиотеку (внешняя компонента это технически динамическая библиотека), то сначала нужно создать бибилиотеку на Rust, а потом на C++.

Для этого нужно подготовить среду для сборки.

Для Rust, нужно скачать и установить приложение-установщик со страницы https://www.rust-lang.org/ru/tools/install.

Для C++ нужно скачать и установить visual studio со страницы https://visualstudio.microsoft.com/vs/community/.

Для разработки на Rust я использую две IDE, VSCode и RustRover.

Открою каждую папку в своей IDE (С++ в visual studio, Rust в RustRover).

Важно! Открывать С++ нужно через CMake файл

-5

И выбрать файл CMakeLists.txt из папки которая была создана при нажатии на "Собрать"

-6

В проекте на С++ для каждой добавленной в конструкторе функции будет создан одноименный файл *.cpp

-7

Который вызывает метод на Rust

-8

Для моей текущей задачи в коде на С++ ничего менять и добавлять не нужно.

Перейду к кода на Rust. Отрою его в IDE RustRover.

В Rust так же для каждого метода добавленного в конструкторе будет создан одноименный файл.

-9

Для моей текущей задачи так же ничего дорабатывать в коде на Rust не нужно, так как сгенерированный код и так по умолчанию возвращает строку "returder value from rust".

Поэтому просто соберу библиотеку на Rust командой cargo build

-10

После сборка в каталоге rust появится собранная статическая библиотека (файл с расширением lib)

-11

Теперь нужно создать динамическую библиотеку (чем является компонента) на стороне С++

Статическая библиотека уже прописана в фале CMakeList.txt, добавлять ее не нужно. Исходные файлы так же автоматически добавлятся при генерации кода  конструктором.

-12

После сборки в каталоге cpp также появится собранная библиотека, уже динамическая (файл с расширением dll)

-13

Все готово! Можно использовать компоненту в 1С.

В созданном каталоге также есть шаблон обработки для тестирования компоненты.

-14

Добавлю в конфигураторе вызов моего метода

-15

И запущу в режиме предприятия.

-16

При запуске вывелась строка, которую возвращает метод Rust.

Второй пример, посложнее. Метод должен получить данные из SQLite и вернуть в виде строки (список пользователей).

Добавлю еще одни метод, назову его ПолучитьПользователей

-17

И аналогично нажму "Собрать" на закладке "Сборка".

В С++ и Rust, аналогично первому примеру, так же добавились файлы для реализации новой функции.

-18

Для работы с библиотекой SQLite в Rust я буду использовать крейт (так в rust называются библиотеки или пакете, терминологически правильно говорить крейт) rusqlite.

Так как я собирают приложение на rust  в статическую библиотеку, то все ее зависимости так же должны быть включены в нее статически, включая библиотеку rusqlite.

Для этого в файле cargo.tolm в секции "Зависимости" укажу

-19

bundle означает что rusqlite будет включена в мою библиотеку статически.

Полный код на rust для файла impl_GetUsers.rs, которы реализует метод ПолучитьПользователей(), будет такой.

-20

Функция getUsers выполняет запрос и возвращает пользователей в виде вектора строк (вектор в rust это аналог динамического массива).

Функция main через метод join объединяет элементы вектора в строку и возвращает функции на C++, которая уже вернет его функции на встроенном языке.

Так же как и в прошлом примере соберу сначала библиотеку на Rust , а потом на С++ (полностью аналогично первому примеру).

Добавлю метод в обработку.

-21

И выполню в режиме предприятия.

-22

Конструктор распространяется бесплатно.

Ссылка на git hub https://github.com/kovalevdmv/onec_comp_gen

Готовые сборки (из раздела релизы) https://github.com/kovalevdmv/onec_comp_gen/releases/