Разработка внешних компонент для мобильного клиента 1С на языке C++ — задача не из легких. Одной из самых серьезных преград становится процесс отладки native-кода (NDK). Когда стандартные средства не дают полной картины, на помощь приходит VisualGDB. Однако при его использовании программисты часто сталкиваются с неочевидными ошибками, такими как «Указаны некорректные знаки в пути» или невозможность подключения отладчика к процессу. В этой статье мы подробно разберем, как настроить окружение, подготовить пакет мобильного клиента и успешно запустить отладку вашего кода.
Поскольку мы работаем с мобильным клиентом, который является «чужим» по отношению к нашей библиотеке приложением, нам необходимо подготовить его так, чтобы Android разрешил подключение отладчика. Проанализируем основные манипуляции с APK-файлом:
AndroidManifest.xml необходимо установить атрибут android:debuggable="true" внутри тега application. Без этого ни один отладчик не сможет «зацепиться» за процесс приложения.lib вашего APK (в подпапки соответствующих архитектур, например, armeabi-v7a или x86) необходимо вручную поместить файл gdbserver. Его можно найти в составе Android NDK.Рассмотрим одну из самых частых ошибок: «Указаны некорректные знаки в пути». Выясним причину этого поведения 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, который будет автоматически конвертировать файл в нужный формат перед запуском сессии отладки.
Современные версии Android (начиная с 9.0) практически отказались от поддержки GDB в пользу LLDB. Рассмотрим, как адаптировать проект под эти реалии. В настройках проекта VisualGDB (Debug Settings) следует проверить метод отладки. Если ваше устройство работает на свежей версии ОС, переключение на LLDB может решить большинство проблем с «отваливающимся» соединением.
Для того чтобы точки останова (breakpoints) стали активными, VisualGDB должен знать, где лежат отладочные символы. В APK-файл попадают «стрипнутые» (stripped) библиотеки, из которых удалена вся лишняя информация для уменьшения размера. Разберем, как указать путь к символам:
obj/local/[архитектура], где лежат файлы .so, содержащие отладочную информацию.Разработка внешней компоненты для 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.
Внешние компоненты 1С загружаются динамически в момент обращения к ним из кода на языке 1С. Это создает ситуацию, когда VisualGDB может попытаться подключиться к процессу раньше, чем ваша библиотека будет загружена в память. В этом случае точки останова могут не сработать.
Рассмотрим два способа решения этой проблемы:
__android_log_print для вывода отладочной информации в Logcat. Это поможет убедиться, что библиотека загружена и функция VInit (или аналогичная) была вызвана.Пример отладочного вывода в 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 необходимо:
gdb.setup.Соблюдение этих правил позволит вам не тратить время на борьбу с инструментарием и сосредоточиться на логике вашей внешней компоненты для мобильной платформы 1С.