본문 바로가기

구글과인터넷/안드로이드

안드로이드 NDK에서 C++ STL 사용

이클립스 CDT 에서 NDK 로 C++ STL을 쓸떄 에러가 난다.

해당 프로젝트에 오른쪽 마우스로 속성에 들어간다음.

 "C/C++ General->Paths and Symbols"  란에 들어간다.

거기에서 add 추가 버튼을 누루고

${ANDROID_NDK_ROOT}\sources\cxx-stl\stlport\stlport

을 설정해 주면 된다. 

추가:
ANDROID_NDK_ROOT <- 는 자신이 설정한 NDK 루트 환경변수.
환경변수가 없으면 NDK 설치 경로를 써도 된다

I had the same problem, and then realized that I need to put: APP_STL := stlport_static

in Application.mk, not Android.mk ... doh

Then I needed to add: ${ANDROID_NDK_ROOT}\sources\cxx-stl\stlport\stlport

to the include paths in eclipse to make it not complain in the UI about errors



//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

출처: http://blog.naver.com/harksoo1974?Redirect=Log&logNo=70100620563


[NDK R5] 기준

subtle ABI(Application Binary Interface)

  • ARM의 CPU와 인터페이스 하기 위한 표준 규약인것 같음.

 

toolchain 이란?

  • 원하는 target system의 sw를 개발하기 위한 host system의 compile 환경을 말함.
  • Compile 환경은 주로 Target과 host가 다르기 때문에 cross-compile 환경 이라고 함.

 

Android는 JNI 를 통해서 native code를 사용할 수 있도록 지원함.

 

JNI(Java Native Interface)?

  • Java가 JVM에 native method를 적재(locate)하고 수행(invoke)할 수 있도록 한다.
  • JNI가 JVN 내에 포함 되므로써, JVM이 호스트 운영체제상의 입출력, 그래픽스, 네트워킹, 스레드와 같은 긴으들을 작동하기 위한 로컬시스템호출(local system calls)을 수행 할 수 있도로 한다.

 

Android NDK R5 부터 STL을 지원을 한다.

 

Application.mk 을 JNI 폴더에 생성

Application.mk에 APP_STL := stlport_shared( or stlport_static) 항목 추가

현재(Android NDK R5)는 STL의 전체 기능을 제공은 stlport에서만 제공 (APP_STL :=system : gnu stl 사용)

 

예)

APP_STL := stlport_static

 

참조 :

명령어 : install. rm, mv, awk, cp, mkdir

명령어: toolchains 컴파일러 사용

android-ndk-r5/toolchains/arm-linux-androideabi-4.4.3/prebuilt/windows/bin/arm-linux-ndroideabi-g++

android-ndk-r5/toolchains/arm-linux-androideabi-4.4.3/prebuilt/windows/bin/arm-linux-androideabi-ar

 

$ANDROID_NDK_ROOT/ndk-build -B V=1 실행을 하면

컴파일 시에 jni 위의 폴더에 사용하고자 하는 프로젝트의 "AndroidManifest.xml "를 넣어서 컴파일 하도록 한다.

위의 파일이 있을 경우 컴파일이 되면, gdb.setup, gdbserver 가 추가적으로 생성이 된다.
1. 컴파일을 한다.

(arm-linux-ndroideabi-g++ )

2. 아카이브 처리 

(arm-linux-androideabi-ar)

3. 라이브러리 복사

4. 링크를 실행

(arm-linux-ndroideabi-g++ )

5. install 실행한다.

 

실행 로그

===============================================================================================

harksoo@harksoo-PC ~/android-ndk-r5/App/ShowMeInterface/jni
$ /home/harksoo/android-ndk-r5/ndk-build
Gdbserver      : [arm-linux-androideabi-4.4.3] libs/armeabi/gdbserver
Gdbsetup       : libs/armeabi/gdb.setup
Compile++ thumb  : ShowMeInterface <= jniShowMeInterface.cpp
Compile++ thumb  : ShowMeInterface <= Common.cpp
Compile++ thumb  : ShowMeInterface <= HttpSocket.cpp
Compile++ thumb  : ShowMeInterface <= msgBody.cpp
Compile++ thumb  : ShowMeInterface <= Parameter.cpp
Compile++ thumb  : ShowMeInterface <= ShowMeInterface.cpp
Compile++ thumb  : ShowMeInterface <= stringUtil.cpp
Compile++ thumb  : ShowMeInterface <= trace.cpp
Compile++ thumb  : ShowMeInterface <= UpdateParam.cpp
SharedLibrary  : libShowMeInterface.so
Install        : libShowMeInterface.so => libs/armeabi/libShowMeInterface.so

===============================================================================================

 

cygwin에서 drive 설정 방법

cd /cygdrive/d

 

NDK의 라이브러리를 사용하는 방법

: windows의 LIB, Dll 의 배포와는 다르게 NDK는 함수 헤더파일을 만들어서 배포하지 않는다.

  JAVA 클래스에 interface할 함수 정의를 한 후 이것에 대하여 헤더파일을 생성한다.(javah 이용)

  이 헤더 파일과 동일한 함수 정의로 선언하여 처리하면 된다.

  1. Eclips로 Android Project를 생성해야 한다.
  2. Activity Class에 Native function을 설정해야 한다.
  3. 해당 프로젝트의 bin에 가서 "javah com.test.HelloJni.HelloJniActivity(경로에 클래스명 포함)" 를 실행. (프로젝트 생성시 Activity  class 이름임)
    NDK에서 사용하는 원시 함수의 헤더파일을 생성해준다.
    예)
    harksoo@harksoo-PC /cygdrive/d/workspace/HelloJni/bin$ javah com.mtelo.ShowMeInterface.ShowMeInterface
  4. 생성된 해더 파일의 함수와 구현코드의 함수명을 같게 해줘야 한다.
    예) jstring Java_com_test_HelloJni_HelloJniActivity_stringFromJNI( JNIEnv* env, jobject thiz )
  5. NDK lib를 만들 폴더 생성, 그안에 JNI 폴더 생성, Android.mk 생성, Application.mk  생성한다.
    Android.mk의 내용
    -> 일반적인 LIB 생성 내용과 동일 : TODO : 추후 내용 추가 예정

    Applicatioin.mk 의 내용
    (아래의 내용 기제시 STLPORT의 STL를 사용할 수 있다.)
    stlport_shared일 경우 동적링크이기 때문에 해당 파일을 같이 배포를 해야 합니다. : TODO : 테스트 안함.

    APP_STL := stlport_static or APP_STL := stlport_shared

  6. JNIEnv* env 를 접근시에 (외부로 데이터를 줄 경우) : 
    C는 (*env)->NewStringUTF(env, "Hello from JNI !") 형식을 사용하지만,
    C++는 env->NewStringUTF(s.c_str()); 형식을 사용하여 구현한다.
    예)
    jniEnv->NewStringUTF(fieldValue);

    확인안된 방법
    const char* reschr2 = jniEnv->GetStringUTFChars(fieldName, JNI_FALSE);
    jniEnv->ReleaseStringUTFChars(fieldName, reschr2);
    jniEnv->DeleteLocalRef(fieldName);
  7. 외부에서 데이터를 받을 경우

 

JAVA 타입과 C/C++ 타입의 맵핑 테이블

참조 : http://gcc.gnu.org/java/papers/native++.html

Java typeC/C++ typenameDescription
bytejbyte8-bit signed integer
shortjshort16-bit signed integer
intjint32-bit signed integer
longjlong64-bit signed integer
floatjfloat32-bit IEEE floating-point number
doublejdouble64-bit IEEE floating-point number
charjchar16-bit Unicode character
booleanjbooleanlogical (Boolean) values
voidvoidno value

 

 

 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////