Введение
Не так давно, для создания одного web-приложения на OneScript, мне понадобились компоненты для преобразования текста из формата markdown в html, а также чтения файлов в формате yaml. После изучения руководства, необходимые компоненты были созданы и я мог использовать их в своем web-приложении. Однако, в связи с отсутствием отладки в http-сервисах OneScript, разработка web-приложения велась в конфигураторе 1С:Предприятие, благо переносимость обеспечивается на уровне Ctrl+C, Ctrl+V. В связи с этим встал вопрос о том, как обеспечить функционал созданных библиотек в среде 1С:Предприятие, а также обеспечить переносимость кода. Ниже описана методика, позволяющая решить озвученные проблемы . Она не претендует на новизну и является работоспособной компиляцией хорошо известных приемов.
Выбор технологии
Платформа 1С:Предприятия представляет два способа, для подключения сторонних библиотек – это технология внешних компонент (NativeAPI), а также технология COM. Ввиду сложности использования технологии NativeAPI, для реализации функционала внешних компонент в среде 1С:Предприятие была выбрана технология COM. Несмотря на то, что она не является кросплатформенной, создание внешних компонент на основе этой технологии несложно и достаточно подробно описано в различных источниках, например:
https://www.codeproject.com/Articles/7859/Building-COM-Objects-in-C
https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/interop/example-com-class
Поскольку внешние компоненты OneScript используют типы, определенные в ядре движка, их непосредственное использование для создания COM компоненты затруднительно и наиболее быстрым подходом, является копирование функционала внешней компоненты путем создания промежуточных классов или Ctrl+C, Ctrl+V.
Пример реализации
В качестве примера реализации вышеизложенного подхода, используем компоненту преобразования текста, в формате markdown в текст, в формате html. Исходный код, а также бинарные файлы расположены по нижеследующим ссылкам:
https://github.com/jdeshin/OneScript-Markdig
https://github.com/jdeshin/OneScript-Markdig/releases
Данная внешняя компонента OneScript реализует нижеследующие функции (в скобках указаны англоязычные наименования функций):
СконфигурироватьРасширения (ConfigureExtensions)
ПолучитьHtmlИзMarkdown(GetHtmlFromMarkdown)
ПолучитьСтрокуИзMarkdown(GetStringFromMarkdown)
В данном случае, мы создадим COM visible сборку, с функциями, имена которых совпадают с англоязычными наименованиями в компоненте OneScript и скопируем туда функционал исходных функций (в данном случае я использовал Ctrl+C, Ctrl+V).
После компиляции, мы получаем dll, которую можно зарегистрировать как COM объект при помощи regasm и использовать в 1С:Предприятие.
Ниже приведены примеры использования компоненты из среды OneScript и 1С:Предприятие.
1С:Предприятие
ТекстMarkdown = "This is a text with some *emphasis*";
// Создание COM-объекта является платформо-зависимым
Процессор = Новый COMОбъект("MarkdigMarkdownProcessorCom.MarkdigMarkdownProcessor");
Процессор.ConfigureExtensions("yaml+advanced");
ТекстHtml = Процессор.GetHtmlFromMarkdown(ТекстMarkdown);
OneScript
ТекстMarkdown = "This is a text with some *emphasis*";
Процессор = Новый MarkdownПроцессорMarkdig;
Процессор.ConfigureExtensions("yaml+advanced");
ТекстHtml = Процессор.GetHtmlFromMarkdown(ТекстMarkdown);
Как можно увидеть, код использования в 1С:Предприятие и OneScript полностью идентичен, за исключением создания объекта, что позволяет без особых трудозатрат переносить код между платформами.
Более сложный случай
К сожалению, не всегда есть возможность одинаковой реализации интерфейса в компоненте OneScript и COM объекте. В качестве примера такой библиотеки, рассмотрим компоненту, которая преобразует текст в формате yaml в дерево соответствий и массивов. Исходный код, а также бинарные файлы расположены по нижеследующим ссылкам:
https://github.com/jdeshin/OneScript-YamlDotNet
https://github.com/jdeshin/OneScript-YamlDotNet/releases
Данная компонента имеет единственную функцию:
ПрочитатьYaml (ReadYaml)
И все бы ничего, однако функция возвращает не примитивный тип, а в общем случае дерево, состоящее из соответствий, массивов и примитивных типов. Соответственно в 1С:Предприятие эти коллекции будут выглядеть как COM объекты, а доступ к ним будет возможен при условии, что возвращаемые объекты являются COM visible и то, как показывает практика не всегда. На основании всего вышеизложенного возможны два варианта – это написание COM оберток к возвращаемым типам, с реализацией необходимого функционала или реализация функций доступа к элементам коллекций. Выберем второй вариант, как более простой.
Для реализации функционала библиотеки в среде 1С:Предприятие, создадим COM объект, реализующий необходимые функции:
ReadYamlString – осуществляет преобразование и возвращает дерево объектов как COM объект
GetValueType – возвращает тип объекта. 0 – Соответствие (Dictionary), 1 – Массив (ArrayList), 2 – Простое значение
GetByIndex – возвращает объект из массива по индексу.
GetByKey – возвращает объект из коллекции типа Соответствие по ключу.
ToArray – преобразует коллекцию соответствие в массив Структур Ключ, Значение
GetKeyByIndex – получает значение ключа по индексу из массива пар Ключ, Значение
GetValueByIndex – получает Объект по индексу из массива пар Ключ, Значение
После компиляции, мы получаем dll, которую можно зарегистрировать как COM объект при помощи regasm и использовать в 1С:Предприятие.
Теперь мы можем использовать необходимый функционал из 1С:Предприятие, однако, с переносимостью дела обстоят чуть лучше, чем никак.
Для обеспечения переносимости кода на прикладном уровне, создадим общий модуль примерно следующего содержания:
// Модуль, реализующий прикладной интерфейс для работы с компонентой чтения Yaml
// Необходим для переносимости кода, между OneScript и 1С:Предприятие
// Создает новый объект процессора Yaml
//
Функция НовыйYamlПроцессор() Экспорт
// Закомментировать в OneScript
Возврат Новый COMОбъект("YamlDotNetProcessorCom.YamlDotNetYamlProcessor");
// Раскомментировать в OneScript
//Возврат Новый YamlПроцессорYamlDotNet;
КонецФункции
// Функция, эмулирующая одноименную функцию в OneScript
//
Функция ПрочитатьYaml(СтрокаYaml, Процессор = Неопределено) Экспорт
Если Процессор = Неопределено Тогда
Процессор = НовыйYamlПроцессор();
КонецЕсли;
// Раскомментировать в OneScript
// Возврат Процессор.ПрочитатьYaml(СтрокаYaml);
// Закомментировать в OneScript
Объекты = Процессор.ReadYamlString(СтрокаYaml);
Возврат ПолучитьЗначение(Объекты, Процессор);
КонецФункции
// Получает значение объекта в зависимости от типа возвращенного COM-объекта
// Необходимо закомментирвать в OneScript
//
Функция ПолучитьЗначение(Объект, Процессор)
ТипОбъекта = Процессор.GetValueType(Объект);
Результат = Неопределено;
Если ТипОбъекта = 2 Тогда
// Это простое значение, возвращаем его
Результат = Объект;
ИначеЕсли ТипОбъекта = 0 Тогда
// Это соответствие
Результат = Новый Соответствие;
МассивОбъектов = Процессор.ToArray(Объект);
Количество = МассивОбъектов.Count;
Для Индекс = 0 По Количество - 1 Цикл
Ключ = Процессор.GetKeyByIndex(МассивОбъектов, Индекс);
Значение = ПолучитьЗначение(Процессор.GetValueByIndex(МассивОбъектов, Индекс), Процессор);
Результат.Вставить(Ключ, Значение);
КонецЦикла;
ИначеЕсли ТипОбъекта = 1 Тогда
// Это массив
Результат = Новый Массив;
Количество = Объект.Count;
Для Индекс = 0 По Количество - 1 Цикл
Значение = ПолучитьЗначение(Процессор.GetByIndex(Объект, Индекс), Процессор);
Результат.Добавить(Значение);
КонецЦикла;
КонецЕсли;
Возврат Результат;
КонецФункции
Теперь, разместив данный модуль в конфигурации и общих модулях web-приложения OneScript, мы получим прикладной код, который можно переносить между платформами OneScript и 1С:Предприятие простым копированием. В случае вышеописанной библиотеки, прикладной код в OneScript и 1С:Предприятие будет выглядеть примерно следующим образом:
Процессор = YamlПроцессор.НовыйYamlПроцессор();
Объекты = YamlПроцессор.ПрочитатьYaml(СтрокаYaml, Процессор);
Update:
Реализована работа с библиотекой MarkdigMarkdownProcessor как с обработкой для использования совместно с каркасной конфигурацией версии 2.0. Подсистема для сравнения/объединения - БиблиотекаMarkdownПроцессор.
Теперь работа с библиотекой будет выглядеть примерно следующим образом:
Функция ОбработкаВызоваHTTPСервиса(Запрос) Экспорт
Макет = ПолучитьОбщийМакет("ДемоТекстMarkdown");
ПроцессорMarkdown = Обработки.MarkdownПроцессор.Создать();
Результат = ПроцессорMarkdown.ПолучитьHtmlИзMarkdown(Макет.ПолучитьТекст());
Ответ = Новый HTTPСервисОтвет(200);
Ответ.УстановитьТелоИзСтроки(Результат);
Возврат Ответ;
КонецФункции
Реализована работа с библиотекой YamlDotNet как с обработкой для использования совместно с каркасной конфигурацией версии 2.0. Подсистема для сравнения/объединения - БиблиотекаYamlПроцессор.
Теперь, работа с библиотекой в OneScript и 1С:Предприятие выглядит примерно следующим образом:
Функция ОбработкаВызоваHTTPСервиса(Запрос) Экспорт
Макет = ПолучитьОбщийМакет("ДемоYamlПроцессор");
ПроцессорYaml = Обработки.YamlПроцессор.Создать();
Результаты = ПроцессорYaml.ПрочитатьYaml(Макет.ПолучитьТекст());
Ответ = Новый HTTPСервисОтвет(200);
Ответ.УстановитьТелоИзСтроки(Результаты.Получить("ИмяБиблиотеки") + ": " + Результаты.Получить("Описание"));
Возврат Ответ;
КонецФункции
Заключение
Надеюсь, что все вышеизложенное поможет писать код, который можно без особых усилий переносить между OneScript и 1С:Предприятие.