Разработка внешних компонент (ВК) для 1С по технологии Native API традиционно ассоциируется с использованием Microsoft Visual Studio. Однако современные рабочие процессы часто требуют ухода от тяжелых IDE в сторону легковесных редакторов вроде VS Code или настройки процессов CI/CD, где сборка должна происходить в консоли. Основная трудность заключается в том, что DLL, собранная простым вызовом компилятора "по умолчанию", часто отказывается подключаться к 1С. В этой статье мы подробно разберем, как правильно настроить линковщик и компилятор, чтобы ваша компонента успешно распознавалась платформой.
Проанализируем ситуацию: когда мы пишем код на C++, компилятор выполняет так называемое «декорирование» или «манглинг» (name mangling) имен функций. Это процесс добавления служебных символов к названию функции (например, @, _ или суффиксов с размером аргументов), чтобы обеспечить поддержку перегрузки функций. Однако 1С ожидает увидеть в DLL строго определенные точки входа с «чистыми» именами:
GetClassNamesGetClassObjectDestroyObjectЕсли линковщик изменит имя GetClassObject на _GetClassObject@12, платформа просто не найдет нужную функцию и выдаст ошибку при попытке загрузки компоненты. Наша задача — заставить компилятор сохранить имена в первозданном виде.
Рассмотрим пошагово процесс сборки с использованием инструментов Microsoft. Для корректной работы нам понадобится не только сам компилятор cl.exe, но и специальный DEF-файл. Это наиболее надежный способ управления экспортом функций.
Шаг 1: Создание DEF-файла
Создадим файл, например component.def, и пропишем в нем секцию экспорта. Это гарантирует, что линковщик не исказит имена:
LIBRARY "my_component"
EXPORTS
GetClassNames @1
GetClassObject @2
DestroyObject @3
Шаг 2: Компиляция и линковка
Теперь разберем ключи командной строки. Нам нужно определить макросы для Windows и указать путь к заголовочным файлам SDK 1С. Типовая команда для сборки будет выглядеть следующим образом:
cl.exe /O2 /EHsc /MT /D "_WINDOWS" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /I"path_to_1c_sdk" /LD my_component.cpp /link /DEF:component.def /OUT:my_component.dll
Разберем основные флаги подробнее:
/O2 — оптимизация кода по скорости./MT — статическая линковка библиотеки времени выполнения (CRT). Это критически важно: если использовать /MD, пользователю придется устанавливать Visual C++ Redistributable именно той версии, в которой вы собирали ВК. Флаг /MT включает код библиотек прямо в DLL./LD — указывает компилятору создать DLL./DEF:component.def — подключает наш файл определений для сохранения имен функций.Если вы предпочитаете использовать инструменты GNU (например, в VS Code под Windows через MinGW), подход немного изменится. Здесь важно учитывать соглашение о вызовах, особенно для 32-битных систем.
Проанализируем необходимые флаги для g++:
g++ -O2 -shared -static -static-libgcc -static-libstdc++ -Wl,--kill-at -D_UNICODE -I"path_to_1c_sdk" -o my_component.dll my_component.cpp
Посмотрим на специфические параметры:
-shared — создание разделяемой библиотеки (DLL).-static-libgcc и -static-libstdc++ — исключают зависимость от внешних библиотек среды MinGW.-Wl,--kill-at — важнейший флаг для линковщика ld. Он удаляет суффиксы @n из имен экспортируемых функций, что позволяет 1С корректно их инициализировать.Иногда возникает задача собрать Windows-версию компоненты, находясь в ОС Linux. Это возможно с помощью кросс-компиляторов (например, x86_64-w64-mingw32-g++). Однако здесь кроется подвох, о котором часто забывают: регистрозависимость файловой системы.
Выясним причину возможных ошибок: в коде SDK 1С заголовочные файлы могут подключаться как #include "ComponentBase.h". Если на диске файл называется componentbase.h (в нижнем регистре), компилятор на Linux выдаст ошибку, в то время как Windows проигнорировала бы это различие. Перед сборкой убедитесь, что регистр имен файлов в #include и в файловой системе полностью совпадает.
Также не забывайте про разрядность. 32-битный "Тонкий клиент" 1С никогда не загрузит 64-битную компоненту. Вам необходимо собирать две версии DLL (x86 и x64) и упаковывать их в один ZIP-архив с файлом MANIFEST.XML для корректной установки в систему.
После сборки крайне полезно проверить, что получилось "внутри" файла. Если вы используете инструменты Microsoft, воспользуйтесь утилитой dumpbin:
dumpbin /exports my_component.dll
В выводе этой команды вы должны увидеть список функций в секции exports. Если там присутствуют странные символы вроде ?GetClassObject@@... или _GetClassObject@12, значит, ключи линковщика не сработали, и 1С не сможет работать с этой библиотекой. В идеальном случае вы должны увидеть просто GetClassObject.
Подведем итог: секрет успешной сборки внешней компоненты в командной строке заключается не в самом коде C++, а в строгом управлении таблицей экспорта DLL и правильном выборе способа линковки runtime-библиотек. Используя DEF-файлы для MSVC или флаг --kill-at для GCC, вы сможете создавать стабильные и переносимые компоненты без привязки к тяжелым графическим оболочкам разработки.