Android NDK C ++ JNI (nessuna implementazione trovata per nativo ...)


86

Sto cercando di utilizzare NDK con C ++ e non riesco a ottenere la convenzione di denominazione del metodo corretta. il mio metodo nativo è il seguente:

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

con un'intestazione avvolta in extern "C" {} anche.

Tutto si compila bene, crea un file .so e copia nella cartella libs sotto il mio progetto, ma quando eseguo il debug ed eseguo in Eclipse continuo a ricevere un messaggio di log cat che dice "nessuna implementazione trovata per nativo ...". C'è qualcosa che mi manca visto che tutti gli esempi NDK sono in C?

Grazie.


Stai generando i tuoi stub JNI usando javah? Altrimenti, dovresti essere tu. :-P
Chris Jester-Young

7
Molto probabilmente perché non hai chiamatoSystem.loadLibrary
IgorGanapolsky

1
Grazie per la tua domanda. Oggi ho imparato una cosa nuova.
Shady Mohamed Sherif

Risposte:


148

Ci sono un paio di cose che possono portare a "nessuna implementazione trovata". Uno sta errando il nome del prototipo della funzione, un altro non riesce a caricare affatto. Ne sei sicuroSystem.loadLibrary() venga chiamato prima che il metodo venga utilizzato?

Se non hai una JNI_OnLoadfunzione definita, potresti crearne una e fargli sputare un messaggio di log solo per verificare che la lib sia stata inserita correttamente.

Hai già schivato il problema più comune - dimenticarti di usare extern "C"- quindi è quanto sopra o qualche leggero errore di ortografia. Che aspetto ha la dichiarazione Java?


13
Gesù! Lei mi ha salvato ore vale la pena di lavoro - dopo aver letto questo avevo appena ricordato che avevo la mia chiamata loadLibrary commentata ...
zeboidlund

11
Hai salvato anche me! Ho quadruplicato il nome della mia funzione e un paio di altre cose ... ma ho dimenticato la "C" esterna e non l'ho nemmeno notato nella domanda!
Qwertie

1
Ora sul sito della documentazione Android: developer.android.com/training/articles/perf-jni.html#faq_ULE
fadden

2
c'è anche un caso di cui nessuno ha parlato: non puoi usare '_' (trattini bassi) nei nomi delle funzioni poiché i trattini bassi sono interpretati come separatori di pacchetti. Quindi, sono possibili solo i nomi delle funzioni delle maiuscole
Nulik

2
@Nulik: puoi usare '_' se esegui l' escape come "_1".
fadden

18

Un'ulteriore causa di questo errore: il nome del metodo nativo non decorato non deve contenere un trattino basso!

Ad esempio, volevo esportare una funzione C denominata AudioCapture_Ping(). Ecco la mia dichiarazione di esportazione in C:

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

Ecco la mia classe Java che importava la funzione:

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

Non sono riuscito a fare in modo che Android si collegasse dinamicamente al mio metodo nativo fino a quando non ho rimosso il carattere di sottolineatura:

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!
    ...

5
Le occorrenze di "_" nella dichiarazione del linguaggio Java devono essere sostituite con "_1" nella dichiarazione nativa. Vedere la tabella 2-1 in docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/… .
fadden

1
Così ovvio, ma non sono riuscito a capirlo da solo dopo diverse ore di debug ... Grazie, mi hai salvato!
George Atsev

@ user1222021 Ho una domanda, possiamo esportare il metodo cpp per tutte le attività nel progetto, dobbiamo specificare il nome dell'attività nel metodo nel file .cpp?
Balflear

14

Ho avuto lo stesso problema, ma per me l'errore era nel file Android.mk. C'è l'ho:

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

ma dovrebbe avere questo:

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

notare il dettaglio + = invece : =

Spero che aiuti.


2
Oppure puoi semplicemente aggiungerli tutti su una riga o utilizzare il carattere di interruzione di riga "\".
IgorGanapolsky

6

Chiamato extern "C" come fornito nell'esempio di Studio generato automaticamente, ma si è dimenticato di racchiudere l'intero resto del file, comprese le seguenti funzioni, tra parentesi {}. Solo la prima funzione ha funzionato.


4

Un motivo in più: utilizza LOCAL_WHOLE_STATIC_LIBRARIES invece di LOCAL_STATIC_LIBRARIES in android.mk. Ciò impedisce alla libreria di ottimizzare le chiamate API inutilizzate perché NDK non è in grado di rilevare l'uso dei collegamenti nativi dal codice java.


1
Dov'è la differenza in: "Usa LOCAL_WHOLE_STATIC_LIBRARIES invece di LOCAL_STATIC_LIBRARIES in android.mk"
Josh


2

Usa javah (parte di Java SDK). È lo strumento esattamente per questo (genera un'intestazione .h dal file .class).


2

Se il nome del pacchetto include _ carattere, è necessario scrivere 1 (uno) dopo _ carattere come mostrato di seguito:

MainActivity.java

package com.example.testcpp_2;

native-lib.cpp

JNICALL
Java_com_example_testcpp_12_MainActivity_stringFromJNI(

0

Provo tutte le soluzioni di cui sopra, ma nessuno può risolvere il mio errore di compilazione (jni java.lang.UnsatisfiedLinkError: Nessuna implementazione trovata per ...), alla fine ho scoperto che mi dimentico di aggiungere il mio file sorgente verify.cpp a CMakeList.txt add_library segement (verify.cpp è generato automaticamente da Ctrl + Invio breve chiave, forse un altro nome di file), spero che la mia risposta possa aiutare qualcuno.

il mio ambiente di costruzione: Gradle + CMake


0

Ho affrontato lo stesso problema, e nel mio caso il motivo era che avevo il carattere di sottolineatura nel nome del pacchetto "RFID_Test" Ho rinominato il pacchetto e ha funzionato. Grazie user1222021


-3

Ho affrontato lo stesso problema due volte. È successo che il telefono con cui ho provato ad avviare l'app da Android Studio usasse un livello API che non ho ancora scaricato in Android Studio.

  1. Aggiorna Android Studio alla versione più recente
  2. Scarica l'API necessaria da Android Studio
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.