К статье
Практический материал

Разработка и Конфигурация · 11 мин

Как сделать внешнюю компоненту для 1С

Как разработать внешнюю компоненту для 1С по технологии Native API: структура проекта на C++, регистрация методов, подключение в конфигурации и типичные ошибки.

Внешняя компонента для 1С — это динамическая библиотека (DLL для Windows, SO для Linux), которая расширяет возможности платформы: работа с оборудованием, шифрование, интеграция с нестандартными API, вычисления, которые неудобно или медленно выполнять на встроенном языке. Платформа 1С:Предприятие поддерживает два механизма создания компонент: устаревший COM-подход и современную технологию Native API, которую фирма «1С» рекомендует для всех новых разработок.

Native API — это открытый интерфейс на C++, описанный в заголовочных файлах, которые поставляются вместе с платформой. Компонента, собранная по этой технологии, работает и на тонком, и на толстом клиенте, и на сервере 1С, а также может использоваться в веб-клиенте через расширение работы с файлами. Именно Native API рассматривается в этом материале как основной вариант.

Для разработки понадобятся: компилятор C++ (Visual Studio для Windows или GCC/Clang для Linux), заголовочные файлы Native API из каталога платформы, базовое понимание работы с указателями и памятью. Глубокое знание C++ не требуется — интерфейс компоненты предельно прост, основная сложность обычно заключается в прикладной логике самой библиотеки.

Когда внешняя компонента действительно нужна

Прежде чем браться за C++, стоит убедиться, что задача не решается штатными средствами. Компонента оправдана, когда нужно: работать с оборудованием через vendor-библиотеки (сканеры, ККТ с нестандартным протоколом, весы), выполнять криптографические операции, не покрытые платформой, обращаться к нативным API операционной системы, ускорить ресурсоёмкие вычисления, интегрироваться со сторонними SDK, поставляемыми только в виде бинарных библиотек.

Если задача — вызвать HTTP-сервис, разобрать JSON или выполнить запрос к базе, внешняя компонента не нужна: всё это платформа делает встроенными средствами. Лишняя нативная библиотека — это дополнительная точка отказа, необходимость поддержки сборок под разные ОС и архитектуры, а также риски безопасности.

Маршрут решения

Нужна ли компонента

Задача решается HTTP-запросами, XML/JSON или встроенными объектами платформыИспользуйте штатные средства 1С — компонента не нужна
Нужен доступ к оборудованию или SDK, поставляемому только как DLL/SOРазрабатывайте внешнюю компоненту по Native API
Нужна интеграция с COM-объектом Windows и клиент только под WindowsДопустим COM-подход, но для новых проектов предпочтительнее Native API

Подготовка инструментов и структуры проекта

Заголовочные файлы Native API находятся в каталоге установки платформы (обычно подкаталог с подпиской ITS или в составе дистрибутива технологической платформы). Ключевые файлы: ComponentBase.h, AddInDefBase.h, IMemory.h и вспомогательные типы. Их нужно подключить к проекту и указать пути в настройках компилятора.

Минимальный проект состоит из одного класса, наследующего IComponentBase, и точек входа — функций GetClassObject и DestroyObject, которые платформа вызывает при загрузке библиотеки. Удобно сразу заложить структуру: отдельный файл с реализацией интерфейса, отдельный — с прикладной логикой, чтобы код интеграции с 1С не смешивался с бизнес-логикой.

Реализация интерфейса IComponentBase

Класс компоненты обязан реализовать набор виртуальных методов. Ключевые из них: Init (получение указателя на интерфейс соединения с платформой), RegisterExtensionAs (регистрация имени компоненты, под которым она будет видна в 1С), GetNProps и GetNMethods (количество свойств и методов), GetPropName/GetMethodName (их имена на русском и английском языках), CallAsProc и CallAsFunc (выполнение методов), GetPropVal/SetPropVal (работа со свойствами).

Обмен данными с платформой идёт через структуру tVariant — аналог VARIANT в COM. Она поддерживает числа, строки, булевы значения, даты и двоичные данные. Строки передаются в кодировке WCHAR_T (UTF-16 или UTF-32 в зависимости от платформы), поэтому для текстовых полей потребуется корректная конвертация из внутреннего представления вашей библиотеки.

Память для строк, возвращаемых в 1С, выделяется через интерфейс IMemoryManager, указатель на который передаётся в Init. Выделять память обычным malloc и передавать её платформе нельзя — это приведёт к падению процесса при освобождении.

Типичные ошибки реализации
01
Выделение памяти для строк через malloc/new вместо IMemoryManager — падение клиента 1С при освобождении памяти
02
Несовпадение имён методов в GetMethodName и логики CallAsFunc — платформа вызывает не тот код или возвращает ошибку
03
Игнорирование флага isPropReadable/isPropWritable — попытка записать свойство только для чтения приводит к исключению в 1С
04
Возврат строки без завершающего нуля или с неверной длиной — мусор в значениях на стороне 1С

Пример каркаса компоненты

Ниже упрощённый скелет класса компоненты с одним методом. В реальном проекте добавляются обработка ошибок, логирование и собственно полезная логика.

class CMyAddIn : public IComponentBase {

public:

CMyAddIn() : m_iConnect(nullptr), m_iMemory(nullptr) {}

bool Init(void* pConnection) override {

m_iConnect = (IAddInDefBase*)pConnection;

return m_iConnect != nullptr;

}

long GetNMethods() override { return 1; }

bool GetMethodName(const long lMethodNum, const long lMethodAlias,

WCHAR_T** wsMethodName) override {

const wchar_t* name = L"GetVersion";

// выделение памяти через IMemoryManager и копирование имени

return true;

}

bool CallAsFunc(const long lMethodNum, tVariant* pvarRetValue,

tVariant* paParams, const long lSizeArray) override {

// lMethodNum == 0 -> вернуть строку версии в pvarRetValue

return true;

}

// ... остальные обязательные методы

};

Функции-точки входа выглядят так: GetClassObject создаёт экземпляр класса по запрошенному имени, DestroyObject освобождает его. Обе экспортируются из DLL с соглашением вызовов, ожидаемым платформой.

cpp
extern "C" long GetClassObject(const WCHAR_T* wsName, IComponentBase<strong> pInterface); extern "C" long DestroyObject(IComponentBase</strong> pInterface);

Сборка и упаковка компоненты

После компиляции полученная DLL сама по себе работоспособна, но для удобной установки и обновления её принято упаковывать в ZIP-архив вместе с файлом manifest.xml. Манифест описывает, какие библиотеки для каких платформ входят в поставку, и позволяет платформе автоматически выбрать нужную сборку.

Структура архива: в корне — manifest.xml, рядом — файлы библиотек (например, MyAddInWin32.dll, MyAddInWin64.dll, MyAddInLinux64.so). В манифесте для каждой библиотеки указывается атрибут code с именем файла и целевая платформа. Такой архив можно хранить в макете конфигурации и устанавливать методом УстановитьВнешнююКомпоненту из макета — это стандартный способ доставки компонент пользователям.

Порядок сборки и упаковки
  1. 1
    Скомпилируйте библиотеку под каждую целевую платформу и разрядность
  2. 2
    Создайте manifest.xml с перечислением файлов и целевых платформ
  3. 3
    Упакуйте манифест и библиотеки в ZIP-архив
  4. 4
    Поместите архив в макет конфигурации типа «Двоичные данные»
  5. 5
    Проверьте установку через УстановитьВнешнююКомпоненту на чистой машине

Подключение и использование в 1С

В коде на встроенном языке компонента подключается методом ПодключитьВнешнююКомпоненту с указанием пути к файлу или макета. После успешного подключения создаётся объект: Новый("AddIn.ИмяКомпоненты"), где имя — та строка, которую компонента вернула в RegisterExtensionAs. Далее вызываются методы и читаются свойства как у обычного объекта.

Пример: ПодключитьВнешнююКомпоненту("ОбщийМакет.МояКомпонента", "МояКомп", ТипВнешнейКомпоненты.Native); Объект = Новый("AddIn.МояКомп.MyComponent"); Версия = Объект.GetVersion();. Обратите внимание: в тонком клиенте компонента исполняется на машине пользователя, в серверном вызове — на сервере, поэтому библиотека должна быть доступна и корректно работать в обоих окружениях.

Обязательно предусмотрите проверку результата подключения: метод возвращает булево значение, а при неудаче важно вывести пользователю понятное сообщение, а не падать с ошибкой создания объекта. Типичные причины неудачи — несовпадение разрядности, отсутствие зависимых библиотек ОС, блокировка антивирусом.

Контрольные точки

Как проверить результат

Подключение компоненты
Норма

ПодключитьВнешнююКомпоненту вернул Истина

Тревожный признак

Возвращает Ложь или вызывает исключение — проверяйте разрядность и зависимости DLL

Вызов методов
Норма

Методы возвращают ожидаемые значения, строки читаются полностью

Тревожный признак

Обрезанные строки, кракозябры или падение клиента — ошибки работы с памятью и кодировкой

Работа на сервере
Норма

Компонента вызывается из серверного кода без ошибок

Тревожный признак

Работает только на клиенте — на сервере нет нужной сборки или прав

Отладка и типичные проблемы

Отлаживать нативную компоненту удобнее всего, подключившись отладчиком Visual Studio к процессу 1cv8.exe и поставив точки останова внутри методов компоненты. Для этого удобно сначала собрать Debug-версию с символами. Логирование в файл изнутри компоненты тоже сильно упрощает диагностику на машинах, где отладчик недоступен.

К частым проблемам эксплуатации относятся: отсутствие Visual C++ Redistributable на машине пользователя (если библиотека собрана с динамической линковкой CRT), блокировка загрузки DLL антивирусом или политиками безопасности, конфликт версий при обновлении компоненты — старая библиотека остаётся загруженной в процессе до его перезапуска. Последнее особенно важно: обновление компоненты требует перезапуска сеанса 1С.

FAQ

Чем Native API лучше COM-компоненты?

Native API работает на всех клиентах 1С, включая Linux и веб-клиент с расширением, не требует регистрации в реестре Windows и проще в установке. COM ограничен Windows и требует административных прав для регистрации, поэтому для новых разработок фирма «1С» рекомендует именно Native API.

Можно ли написать компоненту не на C++?

Формально интерфейс можно реализовать на любом языке, способном экспортировать C-функции и работать с указателями, — например, на Delphi или Rust. На практике C++ остаётся основным вариантом, поскольку заголовочные файлы и примеры поставляются именно для него.

Почему компонента подключается на клиенте, но не работает на сервере?

Сервер 1С — отдельный процесс, часто на другой машине и под другой ОС. Проверьте, что в манифесте есть сборка под платформу сервера (например, 64-битный Linux), что она установлена в кластере и у учётной записи сервера есть права на её загрузку.

Как обновить компоненту у пользователей?

Стандартный путь — заменить ZIP-архив в макете конфигурации и вызвать УстановитьВнешнююКомпоненту при обновлении. Учтите, что уже загруженная в процесс библиотека не выгружается: пользователям потребуется перезапустить сеанс, чтобы начала использоваться новая версия.

Нужно ли подписывать компоненту цифровой подписью?

Для работы в 1С подпись не обязательна, но она снижает риск блокировки антивирусами и упрощает прохождение проверок безопасности в организациях с жёсткими политиками. Для компонент, распространяемых внешним клиентам, подпись настоятельно рекомендуется.

Что делать, если строки из компоненты приходят обрезанными?

Чаще всего причина в неверном указании длины строки или отсутствии завершающего нулевого символа при заполнении tVariant, либо в выделении памяти не через IMemoryManager. Проверьте, что память выделена методом AllocMemory интерфейса менеджера памяти и строка скопирована целиком с терминатором.

Итог

Что важно запомнить

Внешняя компонента создаётся по технологии Native API: класс C++ реализует IComponentBase, библиотека собирается под все целевые платформы, упаковывается в ZIP с manifest.xml и подключается через ПодключитьВнешнююКомпоненту. Критичны корректная работа с памятью через IMemoryManager, совпадение разрядности и тестирование только на копиях баз.