샘플: hello-jni

이 샘플에서는 NDK로 빌드한 작은 C/C++ 애플리케이션인 hello-jni를 살펴봅니다. 이 샘플은 android-mk 분기 내 ndk-samples 저장소의 hello-jni 디렉터리에 있습니다.

Android.mk

다음 두 줄은 네이티브 소스 파일 이름과 빌드할 공유 라이브러리 이름을 제공합니다. 빌드 시스템에서 lib 접두사와 .so 확장자를 추가하면 빌드된 라이브러리의 전체 이름은 libhello-jni.so가 됩니다.

    LOCAL_SRC_FILES := hello-jni.c
    LOCAL_MODULE    := hello-jni
    

Android.mk 파일의 역할과 이 파일을 사용하는 방법에 관한 자세한 내용은 Android.mk를 참조하세요.

Application.mk

이 줄은 빌드 시스템에 어떤 CPU와 아키텍처에 대해 빌드할지 알려줍니다. 이 예시에서는 빌드 시스템이 모든 지원 아키텍처를 대상으로 빌드합니다.

    APP_ABI := all
    

Application.mk 파일과 그 사용 방법에 관한 자세한 내용은 Application.mk를 참조하세요.

자바 측 구현

helloJNI.java 파일은 hellojni/src/com/example/hellojni/에 있습니다. 함수를 호출하여 네이티브 측에서 문자열을 가져온 후 화면에 표시합니다.

소스 코드에는 NDK 사용자의 관심을 끄는 세 줄이 포함되어 있습니다. 본문에는 이들이 행 순서가 아니라 사용된 순서대로 나와 있습니다.

이 함수를 호출하면 애플리케이션 시작 시 .so 파일이 로드됩니다.

Kotlin

    System.loadLibrary("hello-jni")
    

자바

    System.loadLibrary("hello-jni");
    

이 메서드 선언에서 native 키워드는 함수가 공유 라이브러리에 있음(즉, 네이티브 측에 구현되어 있음)을 가상 머신에 알려줍니다.

Kotlin

    external fun stringFromJNI(): String
    

자바

    public native String stringFromJNI();
    

Android 프레임워크는 이전 단계에서 로드되어 선언된 함수를 호출하고 화면에 이 문자열을 표시합니다.

Kotlin

    tv.text = stringFromJNI()
    

자바

    tv.setText( stringFromJNI() );
    

C 측 구현

hello-jni.c 파일은 hello-jni/jni/에 있습니다. 여기에는 자바 측에서 요청한 문자열을 반환하는 함수가 포함되어 있습니다. 함수 선언은 다음과 같습니다.

    JNIEXPORT jstring JNICALL
    Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
                                                      jobject thiz )
    

이 선언은 자바 소스 코드에 선언된 네이티브 함수에 해당합니다. 반환 유형 jstring자바 네이티브 인터페이스 사양에 정의된 데이터 유형입니다. 이 유형은 실제 문자열이 아니라 자바 문자열을 가리키는 포인터입니다.

jstring 뒤에는 함수 이름이 나옵니다. 함수 이름은 자바 함수 이름 및 함수가 포함된 파일의 경로를 기반으로 합니다. 다음 규칙에 따라 함수 이름을 구성합니다.

  • 앞에 Java_를 추가합니다.
  • 최상위 소스 디렉터리에 상대적인 파일 경로를 설명합니다.
  • 슬래시 대신 밑줄을 사용합니다.
  • .java 파일 확장자를 생략합니다.
  • 마지막 밑줄 뒤에 함수 이름을 덧붙입니다.

이러한 규칙에 따라 이 예에서는 함수 이름 Java_com_example_hellojni_HelloJni_stringFromJNI를 사용합니다. 이 이름은 stringFromJNI()라는 자바 함수를 가리키며, 이 함수는 hellojni/src/com/example/hellojni/HelloJni.java에 있습니다.

JNIEnv*는 VM을 가리키는 포인터이고 jobject는 자바 측에서 전달된 암시적 this 객체를 가리키는 포인터입니다.

다음 줄은 VM API (*env)를 호출하여 여기에 반환 값을 전달합니다. 여기서 반환 값은 자바 측의 함수가 요청한 문자열입니다.

    return (*env)->NewStringUTF(env, "Hello from JNI !
    Compiled with ABI " ABI ".");