Как перевести внешнюю компоненту Native API с Delphi x32 на x64?

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

Переход с 32-битной архитектуры на 64-битную при разработке внешних компонент (ВК) для 1С на языке Delphi часто сопровождается трудностями. Простое переключение целевой платформы в среде разработки в большинстве случаев приводит к тому, что компонента перестает загружаться или вызывает аварийное завершение работы 1С (Access Violation). Разберем по шагам, почему это происходит и как правильно адаптировать код под x64.

Анализируем основную причину сбоев: разрядность типов данных

Главная проблема кроется в том, как Delphi обрабатывает типы данных при смене платформы. Рассмотрим ключевое различие: в архитектуре x32 указатели (адреса памяти) имеют размер 4 байта, а в x64 — 8 байт. При этом тип Integer в Delphi остается 4-байтовым на обеих платформах.

Внешние компоненты 1С на технологии Native API взаимодействуют с платформой через специальные структуры и таблицы виртуальных методов. Если в этих структурах для хранения адресов функций или объектов использовался тип Integer, то при компиляции под x64 происходит следующее:

Исправляем структуру TV8ProcRec и интерфейсные модули

Проанализируем структуру TV8ProcRec, которая часто встречается в старых заголовочных файлах v8napi.pas. Именно она отвечает за передачу указателей на функции компоненты в платформу 1С. Для корректной работы в x64 необходимо заменить типы Integer на Pointer или NativeInt в тех местах, где передаются дескрипторы или адреса.

Пример корректного объявления части структуры:


TV8ProcRec = packed record
  // ... другие поля ...
  Destroy1: Pointer; // Ранее могло быть Integer
  Destroy2: Pointer;
  Destroy3: Pointer;
  // ... другие поля ...
end;

Использование типа Pointer или NativeInt является универсальным решением, так как эти типы автоматически меняют свой размер в зависимости от разрядности компиляции (4 байта для x32 и 8 байт для x64). Это позволяет использовать один и тот же исходный код для обеих платформ.

Проверяем соответствие сигнатур методов

Рассмотрим ситуацию с методами, которые вызываются платформой 1С. В Native API сигнатуры функций должны строго соответствовать ожиданиям платформы. Обратим внимание на то, что в некоторых версиях интерфейсов количество и тип аргументов могут отличаться. Например, функция выполнения метода CallAsProc или CallAsFunc должна корректно обрабатывать количество параметров.

Посмотрим на пример корректного объявления функции для x64:


function TMyAddInObject.CallAsFunc(const lMethodNum: Integer;
  var pvarRetValue: PV8Variant; pvarParams: PV8ParamArray;
  const lSizeArray: Integer): Boolean; stdcall;
begin
  // Реализация метода
  Result := True;
end;

Важно помнить, что в 64-битной Windows директива stdcall по сути игнорируется, так как используется единое соглашение о вызовах Microsoft x64, но ее следует оставлять для совместимости с 32-битной сборкой.

Выравнивание памяти и структура tVariant

Проанализируем работу со структурой tVariant (в Delphi часто описывается как TV8Variant). Это критически важное место, так как через него передаются все данные между 1С и компонентой. В x64 версии платформы 1С ожидает выравнивания по 8-байтовой границе.

Если вы используете packed record, вы принудительно устанавливаете выравнивание в 1 байт. Для x64 это может быть фатально. Рекомендуется:

  1. Использовать директиву {$ALIGN 8} в модулях, описывающих взаимодействие с 1С.
  2. Проверить, что вариантные части записи (union в C++) имеют правильный размер. В x64 размер самой большой части tVariant должен составлять 8 байт (для хранения Int64, Double или Pointer).

Особенности работы с памятью и строками

Выясним причину падений при работе со строками или логами, о которых часто упоминают разработчики. При использовании AssignFile или работе с динамическими массивами в x64, любые ошибки в расчете адресов или переполнение типов приведут к Access Violation.

Важные правила:

Пошаговый алгоритм миграции

Рассмотрим краткий план действий для успешного перехода на x64:

  1. В настройках проекта Delphi (Project Options) добавьте платформу Windows 64-bit.
  2. Откройте файл с определениями типов Native API (v8napi.pas или аналог) и замените все типы Integer, предназначенные для хранения адресов и дескрипторов, на Pointer или NativeInt.
  3. Проверьте структуру TV8ProcRec — поля Destroy и указатели на функции обязаны быть 8-байтовыми.
  4. Оберните все методы компоненты в блоки try ... except. В 64-битных приложениях необработанные исключения внутри DLL мгновенно завершают работу основного процесса 1С.
  5. Убедитесь, что при тестировании вы подключаете компоненту именно в 64-битную версию клиента 1С (проверить можно через «Диспетчер задач» или СистемнаяИнформация.ТипПлатформы).

Следуя этим рекомендациям и внимательно следя за размерами типов данных, вы сможете успешно перевести свои наработки на современную 64-битную платформу, обеспечив стабильную работу расширений 1С.

← На главную