Инициализация глобальных переменных на ноль в Android NDK - PullRequest
6 голосов
/ 16 июня 2011

Я разрабатываю приложение, используя обычный C и последнюю версию Android NDK.Я заметил, что * .so никогда не сбрасывается из памяти, поэтому глобальные переменные сохраняют свои значения при последнем запуске приложения, например, рассмотрим следующий код:

static int init = 0;

void android_main(struct android_app* state)
{
  init = 1;
  dostuff();
}

Когда мое приложение запускается дляв первый раз «init» равен 0 и установлен на 1. Начиная со второго запуска, «init» всегда будет 1, потому что * .so все еще находится в памяти.Но я хочу, чтобы глобальные значения были сброшены до значений по умолчанию при каждом вызове android_main ()!

Так есть ли способ гарантировать, что глобальные значения всегда сбрасываются перед вызовом android_main (), или я должен это сделать?это вручную?(это было бы огромной работой для моего приложения, потому что у меня есть тонны глобалов, распределенных по разным * .c источникам)

Спасибо!

Ответы [ 5 ]

5 голосов
/ 29 июня 2011

Вы как бы между камнем и наковальней. Само по себе то, что инициализированные глобальные данные в разделяемых библиотеках фактически никогда не инициализируются. Начальные значения находятся в самом файле .so в разделах DATA, которые просто копируются в память при загрузке и вуаля! инициализированные данные.

Трудное место заключается в том, что Java JNI по своему дизайну не имеет UnloadLibrary () и указывает, что вызов LoadLibrary () для уже загруженной библиотеки должен игнорироваться.

Это еще более усложняется тем, что вы используете помощник Android NativeActivity, который скрывает вас от любой Java, которая фактически загружает библиотеку, а также от самого кода Activity, где вы можете (возможно) быть в состоянии завершить действие когда ваш нативный код готов.

Я не уверен, что дамп NativeActivity и простое написание тонкой прокладки JNI очень помогли бы, тем не менее, поскольку вы все равно не смогли бы выгрузить или перезагрузить нативный код в любом случае, и явное завершение действия в Android может быть немного хитрым. На самом деле, держу пари, вы МОЖЕТЕ сделать так, чтобы действие закончилось чисто и надежно - это не то, чем я занимаюсь, и поэтому я не очень знаком с ним.

Другой возможностью было бы построить 2 нативные библиотеки. Одним из них будет просто ваше приложение, и в нем вообще не будет кода для Android. Другая библиотека будет загружена NativeActivity с помощью android_main () и всех остальных, и она будет использовать API-интерфейс dlopen () / dlsym () / dlclose () C для загрузки, запуска и очистки библиотеки «app».

Я думаю это может сработать - но я никогда не пробовал. Заголовок для работы с общей библиотекой (dlfcn.h) находится в NDK.

3 голосов
/ 28 июня 2011

Единственное решение, которое я нашел, - это вызов метода exit () в нативном коде c - однако, это имеет побочный эффект также и при закрытии действия. Было бы интересно узнать, нашли ли вы лучшее решение?

0 голосов
/ 26 марта 2014

привет, у меня была похожая проблема с lame: я скомпилировал основную функцию как собственный вызов

но когда я вызвал его с параметрами декодирования, функция перестала работать при вызове с параметрами кодирования после этого. Я думаю, что некоторые статические переменные где грязные.

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

может быть, этот обходной путь может вам помочь

0 голосов
/ 06 июля 2011

Я обрабатываю события onCreate / onDestroy и инициализирую / отключаю любые глобальные переменные в этих функциях. Моя реализация немного отличается тем, что у меня есть действие Java, которое затем вызывает код NDK во время функций onCreate / onDestroy, но вы можете напрямую переопределить NativeActivity :: onCreate (но я не знаю, так как Я попробовал это).

0 голосов
/ 29 июня 2011

Вы должны сделать это вручную (то есть, если вы не хотите явно завершить приложение).Как вы сказали, библиотека все еще находится в памяти, пока не будет уничтожена, и, насколько я знаю, в c нет способа вызвать самопроизвольную повторную инициализацию данных таким образом, по крайней мере, без какого-то очень уродливого взлома, которыйвероятно, в конечном итоге будет больше работы, чем просто делать это вручную.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...