web-dev-qa-db-fra.com

Android NDK C++ JNI (aucune implémentation trouvée pour les applications natives ...)

J'essaie d'utiliser le NDK avec C++ et n'arrive pas à appliquer correctement la convention de dénomination de la méthode. ma méthode native est la suivante:

extern "C" {
JNIEXPORT void JNICALL Java_com_test_jnitest_SurfaceRenderer_drawFromJni
(JNIEnv* env, jclass c)
{
   //
}
}

avec un en-tête enveloppé dans extern "C" {} également. 

Tout se compile bien, crée un fichier .so et les copie dans le dossier libs de mon projet, mais lorsque je débogue et exécute dans Eclipse, je reçois un message de journalisation qui indique "Aucune implémentation trouvée pour les applications natives ...". Y a-t-il quelque chose qui me manque car tous les exemples de NDK sont en C?

Merci.

72
Patrick Kafka

Certaines choses peuvent conduire à "aucune implémentation trouvée". L'une obtient le nom de prototype de fonction incorrect, une autre échoue pour charger le fichier .so du tout. Êtes-vous sûr que System.loadLibrary() est appelé avant que la méthode soit utilisée?

Si vous n'avez pas défini de fonction JNI_OnLoad, vous pouvez en créer une et la faire cracher un message de journal juste pour vérifier que la bibliothèque est bien extraite.

Vous avez déjà esquivé le problème le plus courant - oublier d’utiliser extern "C" - c’est donc ce qui précède ou une légère erreur d’orthographe. À quoi ressemble la déclaration Java?

117
fadden

Une cause supplémentaire de cette erreur: votre nom de méthode native non décorée ne doit pas contenir de trait de soulignement!

Par exemple, je voulais exporter une fonction C nommée AudioCapture_Ping(). Voici ma déclaration d'exportation en C:

JNI_EXPORT int Java_com_obsidian_mobilehashhost_MainActivity_AudioCapture_Ping(JNIEnv *pJniEnv, jobject object);  //Notice the underscore before Ping

Voici ma classe Java qui importait la fonction:

package com.obsidian.mobileaudiohashhost;
...
public class MainActivity extends Activity {
    private native int AudioCapture_Ping();  // FAILS
    ...

Je ne pouvais pas relier dynamiquement Android à ma méthode native avant d'avoir supprimé le trait de soulignement:

JNI_EXPORT int Java_com_obsidian_mobilehashhost_MainActivity_AudioCapturePing(JNIEnv *pJniEnv, jobject object); 

package com.obsidian.mobileaudiohashhost;
...
public class MainActivity extends Activity {
    private native int AudioCapturePing();  // THIS WORKS!
    ...
16
user1222021

J'ai eu le même problème, mais pour moi l'erreur était dans le fichier Android.mk. Je l'avais: 

LOCAL_SRC_FILES := A.cpp
LOCAL_SRC_FILES := B.cpp 

mais devrait avoir ceci:

LOCAL_SRC_FILES := A.cpp
LOCAL_SRC_FILES += B.cpp 

notez le détail + = à la place: =

J'espère que ça aide.

13
ademar111190

Appelé extern "C" comme indiqué dans l'exemple généré automatiquement par Studio, mais vous avez oublié de mettre le reste du fichier, y compris les fonctions suivantes, entre {}. Seule la première fonction a fonctionné. 

4
DragonLord
3
Megha

Une raison supplémentaire: utilisez LOCAL_WHOLE_STATIC_LIBRARIES au lieu de LOCAL_STATIC_LIBRARIES dans Android.mk. Cela empêche la bibliothèque d'optimiser les appels d'API inutilisés, car le NDK ne peut pas détecter l'utilisation des liaisons natives à partir de code Java.

3
John Twigg

Utilisez javah (composant du SDK Java). C'est l'outil pour cela (génère en-tête .h à partir d'un fichier .class).

1
MartinH

J'ai rencontré le même problème et, dans mon cas, la raison était que j'avais un caractère de soulignement dans le nom du paquet "RFID_Test" J'ai renommé le paquet et cela a fonctionné . Merci user1222021

0
F.sh

Si le nom de votre package contient le caractère _, vous devez écrire 1(one) après le caractère _, comme indiqué ci-dessous:

MainActivity.Java

package com.example.testcpp_2;

native-lib.cpp

JNICALL
Java_com_example_testcpp_12_MainActivity_stringFromJNI(
0
oiyio

J'essaie toutes les solutions ci-dessus, mais personne ne peut résoudre mon erreur de construction (jni Java.lang.UnsatisfiedLinkError: Aucune implémentation trouvée pour ...), J'ai enfin trouvé que j'avais oublié d'ajouter mon fichier source verify.cpp à CMakeList.txt add_library segmentage (verify.cpp est généré automatiquement par Ctrl + Entrée, peut-être un autre nom de fichier), espérons que ma réponse pourra aider quelqu'un.

mon environnement de construction: Gradle + CMake

0
user2420449