При разработке первых внешних компонент (ВК) по технологии Native API для платформы 1С разработчики часто сталкиваются с ситуацией, когда библиотека успешно компилируется, функция подключения возвращает успешный результат, но при попытке создания объекта выпадает ошибка: Тип не определен (AddIn.AddInNative.CAddInNative). Разберем по шагам, почему это происходит, как правильно инициализировать классы в C++ и каким образом корректно упаковать компоненту для различных ОС.
Сначала убедимся, что компонента в принципе загружается платформой. Код подключения в 1С выглядит следующим образом:
РезультатПодключения = ПодключитьВнешнююКомпоненту(ПутьККомпоненте, "AddInNative", ТипВнешнейКомпоненты.Native);
Сообщить("Результат подключения: " + РезультатПодключения);
Если РезультатПодключения равен Истина (или "Да"), значит, разрядность DLL и платформы совпадают, и файл загружен в память. Ошибка кроется в следующем шаге — инициализации объекта:
ОбъектКомпоненты = Новый("AddIn.AddInNative.CAddInNative"); // Ошибка здесь!
Выясним причину. В шаблонах с ИТС есть метод GetClassNames(), который возвращает внутренние имена классов. Многие ошибочно полагают, что именно это имя (например, CAddInNative) нужно передавать в конструктор Новый. На самом деле всё работает иначе.
Во внешней компоненте можно описать сразу несколько классов. Их базовые имена мы перечисляем в GetClassNames через разделитель. Однако каждый из этих классов должен реализовывать метод RegisterExtensionAs, который возвращает строковое имя. Именно то имя, которое возвращает RegisterExtensionAs, мы должны передавать в функцию Новый в 1С, чтобы создать экземпляр нужного объекта.
Рассмотрим пример. Если внутри C++ кода метод RegisterExtensionAs вашего класса возвращает строку "MySuperComponent", то в 1С вы должны обращаться к нему так:
ОбъектКомпоненты = Новый("AddIn.AddInNative.MySuperComponent");
При изучении примеров с ИТС можно заметить необычную работу со строками: платформа 1С требует использования специального объекта памяти и функций AllocMemory и FreeMemory. Проанализируем, почему нельзя использовать стандартные операторы new или malloc.
Внешняя компонента и платформа 1С собираются независимыми компиляторами и имеют разные менеджеры кучи (heap). Если компонента выделит память стандартным способом, а платформа попытается ее освободить, произойдет конфликт аллокаторов, что приведет к утечке памяти или аварийному завершению работы (крашу). Поэтому платформа передает компоненте свой интерфейс IMemoryManager. Все строки и бинарные данные, которые ВК возвращает в 1С, должны выделяться строго через AllocMemory. Платформа 1С берет на себя ответственность и сама вызывает FreeMemory, когда сборщик мусора очищает переменные во встроенном языке.
Чтобы компонента работала и на сервере Linux, и на клиенте Windows, используется многофайловый ZIP-архив. Это избавляет программиста 1С от написания сложного кода для определения текущей ОС. Достаточно загрузить один архив.
В корне этого архива должен лежать файл MANIFEST.XML, который объясняет платформе, какой бинарный файл (DLL или SO) взять для конкретного окружения. Рассмотрим структуру манифеста:
<bundle xmlns="http://v8.1c.ru/8.2/addin/bundle">
<component os="Windows" path="MyComp_win32.dll" type="native" arch="i386"/>
<component os="Windows" path="MyComp_win64.dll" type="native" arch="x86_64"/>
<component os="Linux" path="MyComp_lin32.so" type="native" arch="i386"/>
<component os="Linux" path="MyComp_lin64.so" type="native" arch="x86_64"/>
</bundle>
Архивируем этот XML-файл вместе с указанными библиотеками в обычный ZIP-архив. Теперь метод ПодключитьВнешнююКомпоненту будет принимать путь именно к ZIP-архиву (или адрес макета, если архив лежит внутри конфигурации). Платформа 1С распакует архив в кэш и загрузит нужный файл автоматически.
Исторически для сборки Linux-библиотек (.so) разработчикам приходилось поднимать виртуальную машину с Ubuntu/Debian. Современный инструментарий позволяет делать это прямо в Windows.
CMake вместо стандартных решений .vcxproj..so файл в папку сборки Windows.Из-за высокого порога входа (управление указателями, ручное выделение памяти через IMemoryManager, сложные кроссплатформенные сборки) разработчики всё чаще используют альтернативные языки для написания Native API ВК:
Таким образом, разобравшись с логикой методов RegisterExtensionAs и принципами работы с памятью и манифестом, вы сможете легко создавать быстрые и надежные внешние компоненты для платформы 1С.