#java-native-interface #android-ndk
#java-native-interface #android-ndk
Вопрос:
У меня особая проблема с Android и библиотекой JNI, которую я использую. Библиотека JNI называется libBase.so и должным образом включен в APK. Я могу выполнить System.LoadLibrary («База»), и библиотека загружается и может использоваться без каких-либо проблем.
Рассмотрим следующие фрагменты кода:
/* NativeObject.java */
public class NativeObject
{
/* ... */
static
{
System.loadLibrary("Base");
}
}
/* ObjectUtil.java */
public class ObjectUtil
{
public static native NativeObject readNative(String path);
public static native void writeNative(String path, NativeObject obj);
}
Когда я пытаюсь выполнить ObjectUtil.readNative() в начале моей программы, я получаю следующие проблемы в logcat:
05-19 18:57:38.508: WARN/dalvikvm(365): No implementation found for native Lcom/navimatics/base/ObjectUtil;.readNative (Ljava/lang/String;)Lcom/navimatics/base/NativeObject;
05-19 18:59:15.409: ERROR/AndroidRuntime(365): java.lang.UnsatisfiedLinkError: readNative
Насколько я понимаю, поскольку класс ObjectUtil ссылается на NativeObject , загрузка класса ObjectUtil должна привести к загрузке класса NativeObject и, следовательно, к выполнению статического инициализатора NativeObject, который выполняет System.Вызов LoadLibrary(). Тогда непонятно, почему я получаю вышеупомянутые сообщения logcat.
Однако, если я изменю ObjectUtil.java читать следующим образом, исключений нет, и программа работает:
/* ObjectUtil.java */
public class ObjectUtil
{
public static native NativeObject readNative(String path);
public static native void writeNative(String path, NativeObject obj);
static
{
System.loadLibrary("Base");
}
}
Это также работает, если я делаю это:
/* ObjectUtil.java */
public class ObjectUtil extends NativeObject
{
public static native NativeObject readNative(String path);
public static native void writeNative(String path, NativeObject obj);
}
Любая помощь по этому вопросу была бы высоко оценена.
ОБНОВЛЕНИЕ: исходный код, о котором меня просили, это:
static jobject JNICALL readNative(JNIEnv *env, jclass jcls, jstring jpath)
{
// ...
}
static void JNICALL writeNative(JNIEnv *env, jclass jcls, jstring jpath, jobject jobj)
{
// ...
}
static JNINativeMethod methods[] =
{
{ "readNative", "(Ljava/lang/String;)Lcom/navimatics/base/NativeObject;", readNative },
{ "writeNative", "(Ljava/lang/String;Lcom/navimatics/base/NativeObject;)V", writeNative },
};
Методы регистрируются с помощью JNIEnv.registerNatives().
Комментарии:
1. Вы не предоставили код объявлений на собственной стороне, и ответ лежит там
2. Код добавлен в соответствии с запросом.
Ответ №1:
У вас есть две дополнительные круглые скобки при инициализации массива JNINativeMethod, этот код не должен компилироваться.
Проверьте код возврата registerNatives(), в случае успеха он должен быть равен нулю.
Также, если вы компилируете код на C , вам следует объявить собственные методы extern "C"
, чтобы избежать их искажения.
Комментарии:
1. Огниан, ты прав насчет круглых скобок. Однако дополнительные круглые скобки не существуют в исходном коде. Исходный код содержит ряд макросов, которые я расширил вручную, отсюда и проблемы, которые вы видели. Исправлено.
2. Однако я не согласен с наблюдением extern «C». Напомним, что registerNatives() регистрирует указатели на функции. Имена этих статических функций не имеют значения.
3. Вы правы насчет
extern "C"
. Вы проверили возвращаемое значениеRegisterNatives
, они были успешно зарегистрированы?4. registerNatives() возвращает успех, если он вызывается. Как объяснялось, если я явно вызываю System.LoadLibrary (), а затем ObjectUtil.readNative(), он работает без проблем. Проблема возникает только тогда, когда я вызываю ObjectUtil.readNative (), предварительно не вызвав System.LoadLibrary(). Однако это не должно вызывать проблемы, потому что ObjectUtil ссылается на класс NativeObject, который вызывает System.LoadLibrary() в статическом инициализаторе. Пожалуйста, смотрите мой оригинальный пост для полного объяснения.