2012-07-24 2 views
5

저는 jni를 처음 접했고, 간단한 네이티브 메소드를 구현하기위한 튜토리얼을 다룰 예정 이었지만, 만족하지 못하는 링크 오류가 발생했습니다. 지금까지 내가 아는 한, 튜토리얼의 단계를 정확히 따라 갔다. 도와주세요. LOCAL_PATH안드로이드에서 jni 사용하기 : UNsatisfiedLinkError

: = $

은 $을 포함한다 (내-DIR 전화)처럼 여기 내 Android.mk 파일이 어떻게 표시되는지를 보여줍니다

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

: 여기

는 자바 래퍼 코드 (CLEAR_VARS)

LOCAL_MODULE : = 제곱 LOCAL_SRC_FILES : = squared.c

는 $ (BUILD_SHARED_LIBRARY)

다음

이처럼 내 .c 파일이 보이는 무엇을 포함한다 : 내 .H 파일이 모습입니다 여기

#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); 
} 

과 같은 :

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 

답변

8

귀하 JNI 서명이 일치하지 않습니다. 당신의 .c 파일에서 변경 :

JNIEXPORT jint JNICALL Java_org_edwards_1research_demo_jni_SquaredWrapper_squared 

JNIEXPORT jint JNICALL Java_com_cookbook_jni_SquaredWrapper_squared 

에 일반적으로 자바 기능 JNI를 통해 "접착제"네이티브 C하는 방법은 두 가지가 있습니다. 첫 번째는 여기에서하려고하는 것입니다. JNI가 해당 Java 코드를 인식하고 연관시키는 미리 결정된 서명을 사용하는 것입니다. 두 번째 방법은 라이브러리를 포함 할 때 함수 포인터, 서명 및 Java 클래스 이름을 JNI로 전달하는 것입니다.

여기에 해당하는 Java 코드의 기본 기능 (이 것이 당신의 .c 파일)에 결합 할 두 번째 방법이다 :

#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; 

} 

그것은 더 좋은 거래의를하지만, 그것은 당신에게 더 많은 유연성 때 제공 바인딩 원시 코드. 제곱 및 포함에 대한 정의는 예상대로입니다. 4 행에서 static const char * SquaredWrapper는 제곱 할 바인드 할 클래스의 완전한 패키지 이름을 가진 이스케이프 된 문자열입니다. 라이브러리의로드와 언로드시에 함수의 바인딩과 언 바인딩을 담당하는 JNI_OnLoad와 JNI_OnUnLoad 함수가 맨 아래에있다. 마지막 부분은 JNINativeMethod 배열입니다. 이 배열은, 각 엔트리로서 사이즈가 3의 배열을 보관 유지합니다. 그 구성 요소는, 메소드의 Java 명, const char *, Java 메소드의 JNI 서명, 및 그 메소드에 바인드하는 네이티브 C 함수 포인터입니다. JNI 함수 시그 니챠는, 환경에 인수의리스트 형식과 Java 함수의 반환 값을 알려줍니다. 형식은 "(Arg1Arg2Arg3 ...) Ret"이므로 int 및 double을 사용하고 float을 반환하는 함수는 "(ID) F"의 서명을 가지며 인수를 사용하지 않고 void를 반환하는 함수는 "()V".나는 속기의 대부분을 기억하는이 편리한 컨닝 페이퍼를 사용

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

행운을 빕니다 :)

편집 : 오, BTW, 당신은 가능성이 JNI_OnLoad에 대한 서명을 추가 할 수 있습니다 및 헤더에 JNI_UnOnLoad 및 새 .c 파일을 반영하도록 기본 함수 프로토 타입의 이름을 변경합니다.

+0

정말 고마워요. 내 자신이 멍청하게 느껴진다. 방금 튜토리얼에서 c 파일을 복사하여 붙여 넣었지만, 나는 그가했던 것보다 다른 패키지 이름을 사용했습니다. 따라서 불일치. 나는 두 번째 방법에 대해 들어 보지 못했다. 더 자세한 정보를 읽을 수있는 링크를 게시 할 수 있습니까? 다시 한번 감사드립니다. – user1487736

+0

물론 내가 선호하는 방법은 JNI_OnLoad : http://developer.android.com/guide/practices/jni.html#native_libraries를 사용하고 모든 기능과 서명 배열을 유지하는 것입니다. Lemme은 몇 가지 예제 코드를 작성하고 답변을 수정하겠습니다. – AlcoJaguar