2011-05-20 3 views
1

J'ai un problème particulier avec Android et une bibliothèque JNI que j'utilise. La bibliothèque JNI s'appelle libBase.so et est correctement incluse dans l'APK. Je suis capable de faire System.loadLibrary ("Base") et la bibliothèque est chargée et peut être utilisée sans aucun problème.Android et UnsatisfiedLinkError

Tenir compte des extraits de code suivant:

/* 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); 
} 

Lorsque je tente de faire ObjectUtil.readNative() au début de mon programme, je reçois les questions suivantes: 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 

Mon la compréhension est que parce que la classe ObjectUtil référence NativeObject, le chargement de la classe ObjectUtil devrait forcer le chargement de la classe NativeObject et donc l'exécution de l'initialiseur statique NativeObject qui effectue l'appel System.LoadLibrary(). Il n'est pas clair alors pourquoi j'obtiendrais les messages de logcat susmentionnés.

Cependant, si je modifie ObjectUtil.java comme suit, il ne fait pas exception et le programme fonctionne:

/* 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"); 
    } 
} 

Il fonctionne aussi si je fais ceci:

/* ObjectUtil.java */ 
public class ObjectUtil extends NativeObject 
{ 
    public static native NativeObject readNative(String path); 
    public static native void writeNative(String path, NativeObject obj); 
} 

Toute aide sur ce serait grandement apprécié.

MISE À JOUR: Le code natif côté que je demandé est la suivante:

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 }, 
}; 

Les méthodes sont enregistrés à l'aide JNIEnv.RegisterNatives().

+1

Vous n'avez pas fourni le code des déclarations côté origine, et la réponse se trouve là – ognian

+0

Code ajouté comme demandé. –

Répondre

1

Vous avez deux parenthèses supplémentaires dans l'initialisation du tableau JNINativeMethod, ce code ne doit pas être compilé.

Vérifiez le code retour de RegisterNatives(), il devrait être zéro en cas de succès. De même, dans le cas où vous compilez un code C++, vous devez déclarer les méthodes natives extern "C" pour éviter de les altérer.

+0

Ognian, vous avez raison à propos des parenthèses. Toutefois, les parenthèses supplémentaires n'existent pas dans le code d'origine. Le code original contient un certain nombre de macros que j'ai développées à la main, d'où les problèmes que vous avez vu. Fixé maintenant –

+0

Je ne suis pas d'accord avec l'observation "C" externe. Rappelez-vous que RegisterNatives() enregistre les pointeurs de fonction. Les noms de ces fonctions statiques ne sont pas pertinents. –

+0

Vous avez raison sur 'extern" C "'. Avez-vous vérifié la valeur de retour de 'RegisterNatives', ont-ils été enregistrés avec succès? – ognian

Questions connexes