본문 바로가기

Android

NDK(R5)로 JNI 만들기

반응형
. NDK(리비전 5) 다운(구글 안드로이드 사이트)

2. cygwin 설치 
- Select Packages에서 다음 패키지들 선택
  + devel/gcc-core
  + devel/gcc-g++
  + devel/make
  + editor/vim (Optional)

3. 안드로이드 프로젝트를 만든 후 jni로 사용할 함수 추가

   public native int doTest1(int a);  이런식으로 추가해줌

4. 이클립스에서 빌드 한번 해줌.

5. 프로젝트의 bin 디렉토리로 이동

6. native 함수를 추가한 클레스를 이용하여 .h 파일을 만든다.
   프로젝트/bin/> javah 패키지경로.클레스이름
   ex) javah jasp.JNITest.Test1

7. 해더파일 생성시 함수 인자값의 이름이 지정 되어 있지 않으므로 추가해 넣어주고 
   생성된 .h 파일과 같은 이름의 .c 또는 .cpp 파일을 만든다.
   
   ex) JNIEXPORT jint JNICALL Java_jangsp_JNITest_Test1_doTest1
  (JNIEnv *, jobject, jint);
   이렇게 되있으므로 아래와 같이 수정
       JNIEXPORT jint JNICALL Java_jangsp_JNITest_Test1_doTest1
  (JNIEnv *pEvt, jobject object, jint a);

8. .c 파일에 함수 내용 구현해 넣음

9. Cygwin의 홈디렉토리에 방금 만든 프로젝트 이름과 같은 폴더생성 하고
   그 안에  jni 라는 폴더를 만듬.
    ex) C:\cygwin\home\Administrator\Test1\jni

10. 지금까지 만든 .Java, .class, .h, .c 파일을 jni 폴더에 복사

11. jni 폴더에 Android.mk를 만들어 넣는다.

   LOCAL_PATH := $(call my-dir)
   include $(CLEAR_VARS)
   LOCAL_MODULE    := jangsp_JNITest_Test1  <-생성된 h 파일의 이름과 같이 해줌
   LOCAL_SRC_FILES := jangsp_JNITest_Test1.c  <- 오브젝트 만들때 참조할 파일
   include $(BUILD_SHARED_LIBRARY)

12. cygwin실행후 jni폴더로 이동 후 아래와 같이 빌드를 한다.
   $> ~/NDK 디렉토리 이름/ndk-build -B

13. ~/Test1(프로젝트 이름) 디렉토리에 생성된 libs폴더를 통째로 복사하여
    안드로이드 프로젝트에 넣고 reflash 한다.
    ex) 프로젝트 이름이 Test1일 경우 /Test1/libs 가 되도록 넣음
  
14. System.loadLibrary("jangsp_JNITest_Test1"); 를 사용하여 so 파일을 로딩한다.
    이때 생성된 so 파일에는 제일 앞에 lib가 붙지만 loadLibrary()에 적어줄때는 
    lib 빼고 넣어야 한다.
    그냥 생성된 .h 파일의 이름과 동일하게 넣으면 된다.
    
    ※ 주의 사항 : loadLibrary 사용하는 부분은 javah 로 해더파일을 만든 .java 파일 이여야만 한다.
                   예를들어 Test1.java에 native함수를 추가하고 javah 로 .h 파일을 만들었으면
                   Test1.java  안에서만 함수 호출이 가능하다.

15. 추가했던 native 함수를 사용한다.
    


cpp 사용하기
   - cpp로 된 코드를 가져다 쓰려고 할때 javah로 생성된 .h 파일이 C 형식이라 
     c++로 만들어진 객체를 c 함수안에서 생성해서 호출하는 방법을 사용했다.

1. C++로 코드 작성 (.h .cpp)
   - .h 파일 만들때 javah로 생성한 .h 파일과 같은 형식으로 만든다.
     (ifdef, extern "C" 추가)

2. 컴파일시에 cpp 파일도 같이 링킹되어야 함으로 Android.mk의 LOCAL_SRC_FILES 에 
   cpp 파일 이름을 추가한다.

   ex) MyCplusplus.cpp 파일을 추가 했을 경우

   LOCAL_PATH := $(call my-dir)

   include $(CLEAR_VARS)

   LOCAL_MODULE    := jangsp_JNITest_Test1
   LOCAL_SRC_FILES := jangsp_JNITest_Test1.cpp \
                MyCplusplus.cpp

   include $(BUILD_SHARED_LIBRARY)

3. javah로 생성된 함수 안에서 추가한 클래스를 생성하여 사용함
   ex)
   JNIEXPORT jint JNICALL Java_jangsp_JNITest_Test1_doTest1
          (JNIEnv *pEnv, jobject object, jint a)
   {
        MyCplusplus *mcp = new MyCplusplus();

        int nRet = mcp->GetNumber();
        return nRet; // 바로 return mcp->GetNumber(); 하면 에러남.. ㅠㅠ
   }

4. ndk-build -B 로 빌드한다.

5. so 파일을 가져다 사용한다.
반응형