Android ndk jni 설치및 연동

13,729 views

Published on

android NDK JNI

0 Comments
12 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
13,729
On SlideShare
0
From Embeds
0
Number of Embeds
5
Actions
Shares
0
Downloads
153
Comments
0
Likes
12
Embeds 0
No embeds

No notes for slide

Android ndk jni 설치및 연동

  1. 1. Android NDK JNIS.O.LAB develop by OracleON(이상온)
  2. 2. 안드로이드 NDK- 안드로이드 SDK와 함께 이용되는 개발키트 => 안드로이드 NDK를 사용하면 애플리케이션의 일부 또는 전부를 c/c++로 만들수 있다. => NDK로 만들어진 실행파일은 바이너리코드이다.(기계어)- NDK 포함된 것들 => 컴파일러, 링커,ToolChain,헤더파일,라이브러리,문서, 예제소스- SDK가 기본으로 사용되며, NDK는 보조적인 역할을 하기 위해 사용- NDK에서 할수 있는 것들 => OpenGL/ES , OpenSL/ES(사운드), 센서입력,터치패널 => NativeActivity , 리눅스시스템콜 => Assets폴더로부터 데이터입력(파일을 추가할때마다 빌드필요없다)
  3. 3. 안드로이드 내부구조(계층)- 리눅스 커널 => 하드웨어 추상계층(HAL) => 라이브러리,안드로이드런타임 => 애플리케이션 프레임워크 => 애플리케이션- 안드로이드 런타임 : (달빅VM)- 애플리케이션 프레임워크 : 버튼,텍스트박스 같은 애플리케이션을 동작시키는데 필요한 라이브러리가 포함- 애플리케이션 실행환경 => 자바소스 => VM바이트코드 =>VM =>라이브러리 => 커널- NDK 실행환경 => 네이티브코드 => 라이브러리 => 커널 자바로 만들어지 부분중 NDK코드는 달빅VM을 거치지 않고 바로 라이브러리를 호출한다.
  4. 4. 안드로이드 내부구조(계층)- SDK,NDK같이 개발한 소스는 VM바이트코드+네이티브코드 포함한 하나의 실행파일에 공존하게 된다.- NDK경우 c/c++로 만든코드는 컴파일러와 링커를 거쳐 .so 파일로 생성 => 공유라이브러이 이므로 단독으로 동작할수 없다.- 자바코드 (.dex파일)로 부터 호출하여 .so 모듈을 이용- 자바코드을 빌드할때 모듈(.so)을 이용하여 실행파일(.apk)생성- NDK단점 1. 디버깅이 어렵다 2. 디바이스마다 실행파일 만들어야한다.(하드웨어 의존성)- NDK장점 1. 빠른속도의 데이터 처리(이미지처리, 게임등) 2. c/c++ 라이브러리 사용
  5. 5. 안드로이드 NDK 설치 for OS X- NDK 설치는 압축파일 형태로 배포되어 압축을 풀기만 하면 완료.- 맥OS X 기준으로 설명 1. http://developer.android.com/sdk/ndk/index.html (NDK다운) 2. 임시폴터에 압축풀기 $ tar xvf android-ndk-r5c-darwin-x86.tar.bz2 $ sudo mv android-ndk-r5c /Developer/SDKs/ 3. android-ndk-r5폴더에 포함된 명령어 실행하도록 패스 추가 export $PATH=/Developer/SDKs/android-ndk-r5c:$PATH
  6. 6. 안드로이드 NDK 설치 for Window- Window 기준으로 설명 1. www.cygwin.com에서 시그윈설치(GNU make필요하기 때문) => 리눅스에서 자주 사용되는 명령어를 윈도우에서 가능하게 => Cygwin 설치 시에 Select Packages 단계에서 make를 체크 후 설치 2. 큰 카테고리에 +를 눌러서 활성화 시키면 아래 항목들 활성화 Devel : gcc-core, gcc-g++, make, swing Editor : vim * Devel통째로 받아서 설치 추천~!! 3.Windows 환경변수에서 PATH설정 C:cygwinbin;C:cygwinusrinclude 추가
  7. 7. 안드로이드 NDK 설치 for Window- Window 기준으로 설명 4. http://developer.android.com/sdk/ndk 에서 ndk 를 받는다 5. NDK 의 압축을 푼다. (cygwin/home/계정/하위폴더에 설치) => C:cygwinhomeAdministratorandroid-ndk-r8c 6. cygwinhome(사용자계정)Administrator.bashrc 파일수정 export ANDROID_NDK_ROOT= homeAdministratorandroid-ndk-r8c
  8. 8. 안드로이드 NDK 설치 for Window 6. 환경변수의 시스템변수에서 새로만들기 ANDROID_SDK 변수이름, 값은 설치한디렉토리 ANDROID_NDK 변수이름, 값은 설치한 디렉토리 7. 환경변수의 시스템변수-> PATH 값 설정 C:Program Files (x86)Androidandroid-sdktools; C:Program Files (x86)Androidandroid-sdkplatform-tools; C:cygwinhomeAdministratorandroid-ndk-r8c;
  9. 9. 안드로이드 JNI- 자바에서 c/c++의 함수를 사용할수 있게 해주는 인터페이스- JNI 규약 1. 메모리 관리 => 자바는 달빅VM이 메모리 관리하지만 c/c++은 개발자가 메모리 관리를 책임지고 할당,해제 해야한다. 2. 타입선언 =>자바의 자료형을 c/c++에서 사용할때 자바자료형 앞에j를 붙인다. (예: byte=>jbyte , int=>jint , float=>jfloat , object=>jobject) =>자바의 배열형은 c/c++에서 Array를 붙여서 선언 (예: byte[] => jbyteArray) 3. 시그니처: 메소드를 만들때 사용하는 독특한 형태 =>원시타입은 알파벳 한글자로 표현(byte=>B , long=>J) =>클래스앞에는 L,끝에는 세미콜론을 붙인다. =>클래스명은 패키지명을 포함한 문자열로 지정 (예: Ljava/lang/String; => 자바의 String타입일경우) =>배열은 선투에 [을 붙여서 지정 (예: int[] => [I; , String[]=> [Ljava/lang/String;
  10. 10. 안드로이드 JNI => 인수,반환값은 소괄호(,)로 구분, 반환값 void면 V B=byte, F=float,I=int,J=long, V=void, Z=boolean , C=char (예: void foo(int val) => (I)V String bar(int val) => (I)Ljava/lang/String; void buzz() =>()V 4. JNI에서 C와 C++의 차이 => C에서는 env구조체 함수포인터를 이용해 호출 (예:FindClass함수호출 jclass jklass =(*env)->FindClass(env,"java/lang/Integer"); ) => C++에서는 env인스턴스의 멤버함수를 호출 (예:FindClass함수호출 jclass jklass =env->FindClass("java/lang/Integer"); )
  11. 11. 안드로이드 JNI 5. 메소드 정의 규칙 * 자바측 - 호출하는 함수를 선언할때 native 추가 - loadLibrary()를 이용해 호출할 라이브러리를 지정 public native int addVals(int a,int b); // native 붙인다 static{ System.loadLibrary("calcvals"); //libcalcvals.so 로드 } * c/c++ 측 - 함수명은 java로 시작, 패키지명+클래스명+메서드명 연결하여 기술 - 인수중 처음2개의 인수는 JNIEnv,jObject타입으로 한다. #include <jni.h> jint java_com_solab_calcval_MainActivity_addVals(JNIEnv* env,jObject thiz , jint a, jint b) { return a+b; } =>co.solab.clacval 패키지에 있는 MainActivity 클래스의 addVals메서드 호출
  12. 12. 안드로이드 JNI 6. 리플렉션 => c/c++에서 자바의 클래스에 접근할수 있는 기능(자바함수, 자바 변수 호출) 예: 문자열을 넣으면 숫자값으로 변화하는 자바클래스의 parseInt 함수 호출 jclass jklass= (*env)->FindClass(env,"java/lang/Integer"); - FindClass함수를 이용하여 java.lang.Integer클래스를 가져온다. jmethodID jmethod = (*env)->GetStaticMethodID(env, jklass,"parseInt","(Ljava/lang/String);I"); - jmethod 에 "parseInt"와 인수, 반환값을 전달하고 해당 메서드의 ID를 구한다. if(jmethod == NULL)return; jint value =(*env)->CallStaticIntMethod(env, jklass,jmethod,strInt); - jklass 클래스와 jmethod를 실행 예: intValue라는 int타입의 멤버변수를 가져오는 코드 jfieldID jfieldid = (*env)->GetFieldID(env, instance,"intValue","I"); - 세번째인수 : 가져올 변수명, 네번째인수: 가져올 변수타입 if(jfieldid = NULL)return; jint val = (*env)->GetIntField(env,instance,jfieldid); - GetXXXField 멤버변수를 int 타입으로 가져온다.
  13. 13. 안드로이드 JNI 7. C/C++에서 자바의 배열 사용법 - 자바의 배열을 가져올려면 GetXXXArrayElements(XXX) - releaseArrayElements 배열메모리 영역 해제 8. C/C++에서 자바의 예외 발생 - ExceptionCheck 함수 - ExceptionOccurred 함수 - ExceptionClear 함수 9. 문자열 - UTF-8인코딩된 문자열 jstring jstr =(*env)->NewStringUTF(env, "펭귄"); jsize jlen =(*env)->GetStringLength(env,jstr); const char* bytes =(*env)->GetStringUTFChars(env,jstr,NULL); (*env)->ReleaseStringUTFChars(env,jstr,bytes);
  14. 14. 안드로이드 JNI 10. 대규모 메모리 처리 - 자바에서 C/C++로 이미지 데이터 보내기 1. 자바의 배열을 이용하기 : 자바에서 설정한 배열을 C/C++용으로 변환해서 저장 2. java.nio.ByteBuffer클래스 이용 : 변환과정 필요없어 처리시간 단축 NewDirectByteBuffer(JNIEnv * env,viud* address, jlong capacity) -> 메모리 주소와 크기를 설정하고 새로운 인스턴스 생성 GetDirectBufferAddress(JNIEnv *env, jobject buf) -> 인스턴스를 전달하고 시작주소를 반환한다. GetDirectBufferCapacity(JNIEnv *env, jobject buf) -> 인스턴스를 전달하고 크기를 반환한다. 11. 리틀 엔디언, 빅 엔디언 데이터를 메모리에 저장할때 상위비트부터 저장 : 빅에디언 데이터를 메모리에 저장할때 하위비트부터 저장 : 리틀에디언 =>달빅VM에서는 리틀에디언 사용
  15. 15. 안드로이드 JNI 12. Android.mk 파일 - 안드로이드 NDK를 이용하여 빌드할려면 Android.mk파일이 필요 - c/c++에서 makefile을 만들어서 빌드하지만 안드로이드는 Android.mk 파일만듬 - 모듈을 만드는데 필요한 소스코드 및 링크할 라이브러리 지정 - 문법은 GNU make에 따라 작성 예: clacvlas.c에서 모듈인 libcalcvalc.so 파일을 생성 LOCAL_PATH :=$(call my-dir) include $(CLEAR_VARS) -> 이전의 모든 설정을 정리 LOCAL_MODULE := calcvals -> 생성할 모듈 지정 ,libcalcvalc.so 라는 공유라이브러리가 생성 LOCAL_SRC_FILES := calcvals.c -> 생성된 모듈을 빌드하는데 필요한 소스파일을 지정 include $(BUILD_SHARED_LIBRARY) -> 이 라이브러리는 공유라이브러리로 생성
  16. 16. 안드로이드 JNI- 자바에서 C 함수 호출하기 * int타입만 사용해 사칙연산 메소드 만들기 실습 * 1. 프로젝트 만들기 - cygwin/home/user계정/ 폴더에 프로젝트를 생성한다. - 이클립스에서 프로젝트 생성후 소스코드와 Android.mk 파일위한 jni폴더 추가 2. jni폴터 밑에 Android.mk 파일 생성 LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES := calcvals.c LOCAL_MODULE := calcvals include $(BUILD_SHARED_LIBRARY) => 이 파일에 의해 calcvals.c가 빌드되고 libcalcvals.so파일이 만들어진다.
  17. 17. 안드로이드 JNI 3. MainActivity.java 변경 protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); StringBuffer buf = new StringBuffer(); TextView tv = new TextView(this); int a=10; int b=2; int val = addVals(a,b); buf.append("a+b="+String.valueOf(val)+"n"); val = subVals(a,b); buf.append("a-b="+String.valueOf(val)+"n"); val = mulVals(a,b); buf.append("a*b="+String.valueOf(val)+"n"); val = divVals(a,b); buf.append("a/b="+String.valueOf(val)+"n"); tv.setText(buf.toString()); setContentView(tv); } public native int addVals(int a, int b); public native int subVals(int a, int b); public native int mulVals(int a, int b); public native int divVals(int a, int b); static{ System.loadLibrary("calcvals"); }
  18. 18. 안드로이드 JNI 4. calcvals.h 파일 생성 #include <jni.h> #ifndef _addvals_h #define _addvals_h #ifdef __cplusplus extern "C" { #endif jint Java_com_solab_jnicalc_MainActivity_addVals(JNIEnv* env,jobject thiz,jint a, jint jint Java_com_solab_jnicalc_MainActivity_subVals(JNIEnv* env,jobject thiz,jint a, jint jint Java_com_solab_jnicalc_MainActivity_mulVals(JNIEnv* env,jobject thiz,jint a, jint jint Java_com_solab_jnicalc_MainActivity_divVals(JNIEnv* env,jobject thiz,jint a, jint #ifdef __cplusplus } #endif #endif
  19. 19. 안드로이드 JNI 5. calcvals.c 파일 생성 #include "calcvals.h" jint Java_com_solab_jnicalc_MainActivity_addVals(JNIEnv* env,jobject thiz,jint a, jint b) { return a+b; } jint Java_com_solab_jnicalc_MainActivity_subVals(JNIEnv* env,jobject thiz,jint a, jint b) { return a-b; } jint Java_com_solab_jnicalc_MainActivity_mulVals(JNIEnv* env,jobject thiz,jint a, jint b) { return a*b; } jint Java_com_solab_jnicalc_MainActivity_divVals(JNIEnv* env,jobject thiz,jint a, jint b) { return a/b; }
  20. 20. 안드로이드 JNI 6. 빌드 - 먼저, 프로젝트 폴더로 이동하여 ndk-build명령을 실행한다. - 빌드에 성공하면 libs/armeabi 폴더 아래에 libcalcvals.so생성됨 - 이클립스에서 project -> clean 후에 프로그램 실행

×