Почему при подключении внешней компоненты Native API возникает ошибка "Тип не определен" и как ее исправить?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке первых внешних компонент (ВК) по технологии 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");

Разберем ручное управление памятью в Native API

При изучении примеров с ИТС можно заметить необычную работу со строками: платформа 1С требует использования специального объекта памяти и функций AllocMemory и FreeMemory. Проанализируем, почему нельзя использовать стандартные операторы new или malloc.

Внешняя компонента и платформа 1С собираются независимыми компиляторами и имеют разные менеджеры кучи (heap). Если компонента выделит память стандартным способом, а платформа попытается ее освободить, произойдет конфликт аллокаторов, что приведет к утечке памяти или аварийному завершению работы (крашу). Поэтому платформа передает компоненте свой интерфейс IMemoryManager. Все строки и бинарные данные, которые ВК возвращает в 1С, должны выделяться строго через AllocMemory. Платформа 1С берет на себя ответственность и сама вызывает FreeMemory, когда сборщик мусора очищает переменные во встроенном языке.

Посмотрим на упаковку кроссплатформенной компоненты: ZIP и MANIFEST.XML

Чтобы компонента работала и на сервере 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) из Visual Studio

Исторически для сборки Linux-библиотек (.so) разработчикам приходилось поднимать виртуальную машину с Ubuntu/Debian. Современный инструментарий позволяет делать это прямо в Windows.

  1. Установите подсистему WSL (Windows Subsystem for Linux) на ваш ПК.
  2. В Visual Studio (начиная с 2017/2019) выберите установку средств разработки Linux (C++ for Linux development).
  3. Переведите проект на использование CMake вместо стандартных решений .vcxproj.
  4. Выберите таргет-среду WSL-GCC или Linux-Debug. Visual Studio сама синхронизирует исходники с Linux-окружением, запустит там компилятор (GCC или Clang) и заберет готовый .so файл в папку сборки Windows.

Современные альтернативы классическому C++

Из-за высокого порога входа (управление указателями, ручное выделение памяти через IMemoryManager, сложные кроссплатформенные сборки) разработчики всё чаще используют альтернативные языки для написания Native API ВК:

  1. Rust: Существуют open-source крейты (библиотеки), которые оборачивают интерфейсы 1С в безопасный код. Rust берет на себя вызовы аллокатора 1С и исключает утечки памяти благодаря системе владения.
  2. C# и NativeAOT: В новых версиях .NET появилась возможность компилировать C# код прямо в нативные машинные библиотеки без COM-регистрации. Существуют готовые шаблоны для 1С, позволяющие писать компоненты на C#, которые отлично работают как в Windows, так и в Linux, используя привычный синтаксис и автоматическое управление памятью.

Таким образом, разобравшись с логикой методов RegisterExtensionAs и принципами работы с памятью и манифестом, вы сможете легко создавать быстрые и надежные внешние компоненты для платформы 1С.

← На главную