2012-07-24 24 views
5

jni'ye yeni geldim ve basit bir yerel yöntem uygulamak için bir öğreticiye gidiyorum, ancak bir bağlantısız bir iletişim kuralı alıyorum. Bildiğim kadarıyla, öğreticideki adımları tam olarak takip ettim. Lütfen bana yardım et. LOCAL_PATHAndroid'de jni'yi kullanma: UNsatisfiedLinkError

: = $

$ arasında (benim-dir diyoruz) gibi İşte benim Android.mk dosya nasıl göründüğü ve

package com.cookbook.jni; 

public class SquaredWrapper { 

    // Declare native method (and make it public to expose it directly) 
    public static native int squared(int base); 

    // Provide additional functionality, that "extends" the native method 
    public static int to4(int base) 
    { 
     int sq = squared(base); 
     return squared(sq); 
    } 

    // Load library 
    static { 
     System.loadLibrary("squared"); 
    } 
} 

: Burada

java sarıcı kodudur (CLEAR_VARS)

LOCAL_MODULE: = kare LOCAL_SRC_FILES: = squared.c

$ (BUILD_SHARED_LIBRARY)

İşte

gibi benim .c dosyası nasıl göründüğü ve şunlardır: benim .h dosyasını göründüğünü burada

#include "squared.h" 
#include <jni.h> 

JNIEXPORT jint JNICALL Java_org_edwards_1research_demo_jni_SquaredWrapper_squared 
    (JNIEnv * je, jclass jc, jint base) 
{ 
    return (base*base); 
} 

Ve benzeri:

enter code here/* DO NOT EDIT THIS FILE - it is machine generated */ 
#include <jni.h> 
/* Header for class com_cookbook_jni_SquaredWrapper */ 

#ifndef _Included_com_cookbook_jni_SquaredWrapper 
#define _Included_com_cookbook_jni_SquaredWrapper 
#ifdef __cplusplus 
extern "C" { 
#endif 
/* 
* Class:  com_cookbook_jni_SquaredWrapper 
* Method: squared 
* Signature: (I)I 
*/ 
JNIEXPORT jint JNICALL Java_com_cookbook_jni_SquaredWrapper_squared 
    (JNIEnv *, jclass, jint); 

#ifdef __cplusplus 
} 
#endif 
#endif 

cevap

8

Sizin JNI imzası eşleşmiyor. senin .c dosyasında değişiklik:

JNIEXPORT jint JNICALL Java_org_edwards_1research_demo_jni_SquaredWrapper_squared 

JNIEXPORT jint JNICALL Java_com_cookbook_jni_SquaredWrapper_squared 

için Genellikle bir Java işlevine JNI aracılığıyla "tutkal" doğal C için iki yol vardır. İlki burada yapmaya çalıştığınız şeydir, yani JNI'nin uygun Java kodunuzla tanıdığı ve ilişkilendireceği önceden belirlenmiş bir imza kullanın. İkincisi, kitaplığı eklediğinizde işlev işaretçileri, imzalar ve Java sınıfı adlarını JNI'ye geçirmektir.

Burada uygun bir Java kodu yerli fonksiyonunu (bu olurdu senin .c dosyası) bağlamak istiyorum İkinci yöntem var:

#include "squared.h" 
#include <jni.h> 

static const char* SquaredWrapper = "com/cookbook/jni/SquaredWrapper"; 

jint squared(JNIEnv * env, jobject this, jint base) { 
    return (base*base); 
} 

// Methods to register for SquaredWrapper 
static JNINativeMethod SquareWrapperMethods[] = { 
     {"squared", "(I)I", squared} 
}; 

jint JNI_OnLoad(JavaVM* vm, void* reserved) { 
    JNIEnv* env; 
    if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_6) != JNI_OK) 
     return JNI_ERR; 

    jclass class = (*env)->FindClass(env, SquaredWrapper); 
    (*env)->RegisterNatives(env, class, SquaredWrapperMethods, sizeof(SquaredWrapperMethods)/sizeof(SquaredWrapperMethods[0])); 

    return JNI_VERSION_1_6; 
} 

void JNI_OnUnload(JavaVM* vm, void* reserved) { 
    JNIEnv* env; 
    if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_6) != JNI_OK) 
     return; 

    jclass class = (*env)->FindClass(env, SquaredWrapper); 
    (*env)->UnregisterNatives(env, class); 

    return; 

} 

daha uzun iyi bir anlaşma ama size çok daha fazla esneklik zaman verir yerel kodu bağlama. Kare tanımı ve kapsamları beklediğiniz gibi. 4. satırda, statik const char * SquaredWrapper, kareye bağlamak istediğiniz sınıfın tam nitelikli paket adıyla kaçan bir dizedir. Alt kısımda, kütüphane yükü ve boşaltma işlevlerini bağlama ve bağlama işlemlerini gerçekleştiren JNI_OnLoad ve JNI_OnUnLoad işlevleri bulunur. Son parça JNINativeMethod dizisidir. Bu dizi, her girdiyi, bileşenleri bir const char * yöntemi olarak Java adı, Java yönteminin JNI imzası ve bu yönteme bağlanmak için yerel C işlevi işaretçisi olan bir boyut 3 dizisini içerir. JNI fonksiyon imzası çevreye argüman listesi formatını ve Java fonksiyonunun dönüş değerini bildirir. Biçim "(Arg1Arg2Arg3 ...) Ret" şeklindedir, böylece bir int ve double alır ve bir float döndüren bir işlev "(ID) F" imzasına sahip olur ve hiçbir argüman almayan ve void döndüren bir işlev olur "() V".Ben kestirme en hatırlamak için bu kullanışlı kopya kâğıdı kullanın:

http://dev.kanngard.net/Permalinks/ID_20050509144235.html

İyi şanslar :)

Düzenleme: Ah, BTW, büyük olasılıkla JNI_OnLoad için imza eklemek istersiniz ve JNI_UnOnYerbaşınıza yükleyin ve yeni .c dosyasını yansıtmak için yerel işlev prototipinizin adını değiştirin.

+0

Çok teşekkür ederim. Aptal hissediyorum. Sadece c dosyasını eğiticiden kopyaladım ve yapıştırdım, ama ondan farklı bir paket adı kullandım. Bu nedenle uyumsuzluk. İkinci yolu hiç duymadım. Daha fazla okuyabileceğim bir yere bir bağlantı gönderebilir miyim? Tekrar teşekkürler. – user1487736

+0

Elbette, tercih ettiğim yöntem JNI_OnLoad kullanmaktır: http://developer.android.com/guide/practices/jni.html#native_libraries ve tüm işlevlerimi ve imzalarımı bir dizi tutmak. Lemme bir örnek kod yaz ve cevabımı düzenlerim. – AlcoJaguar