Как отлаживать неуправляемый код (C++) для Android в VisualGDB при разработке внешних компонент 1С

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

Разработка внешних компонент для мобильного клиента 1С на языке C++ — задача не из легких. Одной из самых серьезных преград становится процесс отладки native-кода (NDK). Когда стандартные средства не дают полной картины, на помощь приходит VisualGDB. Однако при его использовании программисты часто сталкиваются с неочевидными ошибками, такими как «Указаны некорректные знаки в пути» или невозможность подключения отладчика к процессу. В этой статье мы подробно разберем, как настроить окружение, подготовить пакет мобильного клиента и успешно запустить отладку вашего кода.

Шаг 1. Подготовка мобильного клиента 1С к отладке

Поскольку мы работаем с мобильным клиентом, который является «чужим» по отношению к нашей библиотеке приложением, нам необходимо подготовить его так, чтобы Android разрешил подключение отладчика. Проанализируем основные манипуляции с APK-файлом:

  1. Флаг debuggable: В файле AndroidManifest.xml необходимо установить атрибут android:debuggable="true" внутри тега application. Без этого ни один отладчик не сможет «зацепиться» за процесс приложения.
  2. Размещение gdbserver: Для корректной работы VisualGDB (если используется старая схема отладки GDB) в папку lib вашего APK (в подпапки соответствующих архитектур, например, armeabi-v7a или x86) необходимо вручную поместить файл gdbserver. Его можно найти в составе Android NDK.
  3. Переподпись приложения: После внесения изменений в APK его необходимо заново подписать. Важно помнить, что если вы используете стандартный отладочный ключ (debug keystore), то перед установкой измененного клиента старую версию приложения с устройства нужно удалить, иначе возникнет конфликт подписей.

Шаг 2. Настройка конфигурационных файлов и решение проблем с путями

Рассмотрим одну из самых частых ошибок: «Указаны некорректные знаки в пути». Выясним причину этого поведения VisualGDB. Проблема часто кроется не в кириллице, а в особенностях парсинга путей самим инструментом и Android NDK.

Во-первых, проверим системные пути. Убедимся, что Android SDK и NDK установлены в папки без пробелов. Путь типа C:\Android\SDK предпочтительнее, чем C:\Program Files (x86)\Android\android-sdk. Также крайне желательно, чтобы сам проект Visual Studio находился по максимально короткому пути в корне диска.

Во-вторых, обратим внимание на файл gdb.setup. Разберем важный технический нюанс: при каждой пересборке проекта через ndk-build в этом файле могут сбиваться символы переноса строк. Если файл сохранен с Windows-переносами (CRLF), отладчик может его не прочитать. Нам необходимо убедиться, что используется UNIX-перенос строк (LF). Проанализируем пример того, как должен выглядеть путь в этом файле:


directory C:/Projects/My1CComponent/jni
set solib-search-path C:/Projects/My1CComponent/obj/local/armeabi-v7a

Если вы заметили, что настройки сбиваются, можно настроить «Pre-build event» в Visual Studio, который будет автоматически конвертировать файл в нужный формат перед запуском сессии отладки.

Шаг 3. Конфигурация VisualGDB и выбор отладчика

Современные версии Android (начиная с 9.0) практически отказались от поддержки GDB в пользу LLDB. Рассмотрим, как адаптировать проект под эти реалии. В настройках проекта VisualGDB (Debug Settings) следует проверить метод отладки. Если ваше устройство работает на свежей версии ОС, переключение на LLDB может решить большинство проблем с «отваливающимся» соединением.

Для того чтобы точки останова (breakpoints) стали активными, VisualGDB должен знать, где лежат отладочные символы. В APK-файл попадают «стрипнутые» (stripped) библиотеки, из которых удалена вся лишняя информация для уменьшения размера. Разберем, как указать путь к символам:

  1. Переходим в VisualGDB Project Properties.
  2. Выбираем раздел Debug Settings.
  3. В поле Symbol Paths добавляем путь к папке obj/local/[архитектура], где лежат файлы .so, содержащие отладочную информацию.

Шаг 4. Работа с JNI и потоками в контексте 1С

Разработка внешней компоненты для 1С на C++ подразумевает интенсивное использование JNI. Выясним, почему отладка может прерываться при вызове функций 1С или обратных вызовов. При работе с Android крайне важно соблюдать правила владения контекстом JNIEnv.

Если ваша компонента создает фоновые потоки (например, для ожидания события от датчиков или сетевого ответа), помните, что каждый новый поток должен быть «приаттачен» к виртуальной машине Java. Посмотрим на пример кода, который часто забывают реализовать, что приводит к краху при отладке:


JNIEnv *env;
JavaVMAttachArgs args;
args.version = JNI_VERSION_1_6;
args.name = "My1CThread";
args.group = NULL;

if (g_vm->AttachCurrentThread(&env, &args) != JNI_OK) {
    // Ошибка: не удалось подключить поток к JVM
    return;
}
// Здесь выполняем работу с JNI
g_vm->DetachCurrentThread();

Без вызова AttachCurrentThread отладчик не сможет показать стек вызовов внутри вашего потока, и приложение просто закроется с критической ошибкой при попытке обращения к любому объекту Java через env.

Шаг 5. Тонкости отладки динамически загружаемых библиотек

Внешние компоненты 1С загружаются динамически в момент обращения к ним из кода на языке 1С. Это создает ситуацию, когда VisualGDB может попытаться подключиться к процессу раньше, чем ваша библиотека будет загружена в память. В этом случае точки останова могут не сработать.

Рассмотрим два способа решения этой проблемы:

  1. Использование логов: Используйте функцию __android_log_print для вывода отладочной информации в Logcat. Это поможет убедиться, что библиотека загружена и функция VInit (или аналогичная) была вызвана.
  2. Принудительная пауза: В начале инициализации компоненты можно вставить временный цикл, который будет ждать изменения глобальной переменной. Вы сможете подключиться отладчиком к уже запущенному процессу, найти эту переменную в памяти, изменить её значение и продолжить выполнение по шагам.

Пример отладочного вывода в Logcat:


#include <android/log.h>
#define LOG_TAG "My1CComp"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)

// В коде функции
LOGI("Компонента загружена, адрес env: %p", env);

Итоги и рекомендации

Подведем итог нашему исследованию. Для успешной отладки NDK в VisualGDB необходимо:

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

← На главную