[자바] JNI에서 jboolean을 bool로 바꾸기


자바에서 JNI를 사용하다 보면 인자로 받은 jboolean을 bool형으로 바꾸어야 할 일이 생깁니다.

그럴 때에는 아래 코드와 같이 하면 됩니다.

JNI_FALSE와 다른지를 검사하는 것이 JNI_TRUE와 같은지를 검사하는 것보다 좀 더 안전합니다.


jboolean foo;

bool bar;


// foo가 JNI_FALSE와 다른지를 검사하기 때문에 foo와 bar이 같은 논리값을 갖게 됩니다.

bar = (bool) (foo != JNI_FALSE);


( 참조한 곳: https://stackoverflow.com/a/10192690/1125721 )

[자바] 밑줄 (_) 이 들어가는 JNI 함수명


JNI에서는 함수명에 자바의 패키지 경로를 모두 쓰게 되는데, 그 때에 .(점)을 _(밑줄)로 치환하게 됩니다. 따라서 자바 함수명 자체에 밑줄이 있으면 문제가 생깁니다. 이런 경우 자바 함수명에 있는 밑줄은 JNI에서 _1로 치환하면 됩니다. 아래는 간단한 예제입니다.


// 자바

package com.tistory.crmn;

public class Hello {

    static native int get_hello();

}



// JNI

extern "C" JNIEXPORT jint JNICALL

Java_com_tistory_crmn_Hello_get_1hello(JNIEnv* env, jobject thiz) { // get_1hello에 주목하세요

    return (jint) 1;

}


[안드로이드] CMakeLists.txt 파일 설명


안드로이드에서 JNI를 통해 C나 C++ 코드를 사용하려면 CMake나 ndk-build중 하나를 사용해야 합니다. 이 글에서는 CMakeList.txt에 사용되는 여러 옵션에 대해 알아보겠습니다.


1. 사용할 CMake의 최소 버전 설정


cmake_minimum_required(VERSION 3.4.1)



2. 안드로이드에서 사용할 라이브러리의 이름과 공유 및 정적 여부, 소스 코드 경로 설정


아래 예제의 경우 라이브러리의 이름은 native-lib이고 공유 라이브러리이며 소스 코드 경로는 src/main/cpp/native-lib.cpp 입니다. 참고로 이렇게 컴파일을 하면 CMake는 컴파일 결과물을 libnative-lib.so 라는 이름으로 저장합니다.


add_library( native-lib

             SHARED

             src/main/cpp/native-lib.cpp )



3. 소스 코드에서 사용하는 헤더 파일이 들어있는 디렉토리 설정


설정해주지 않아도 동기화 이후에는 자동으로 헤더 파일이 인식되기는 합니다만, 설정해주면 컴파일 단계에서부터 연결된 헤더 파일을 볼 수 있습니다.


include_directories(src/main/cpp/include/)



4. 이미 존재하는 안드로이드 NDK 기본 라이브러리 사용하기


find_library()와 target_link_libraries()를 사용하면 안드로이드 NDK에서 기본으로 제공하는 라이브러리를 따로 컴파일할 필요 없이 바로 사용할 수 있습니다. 아래 예제는 NDK에 있는 log라는 라이브러리를 찾아서 log-lib이라는 변수명으로 저장한 뒤에 native-lib에서 불러와서 사용하는 코드입니다. log-lib이 변수명이기 때문에 target_link_libraries() 에서는 ${log-lib} 으로 표기됩니다.


find_library( log-lib

              log )

target_link_libraries( native-lib

                       ${log-lib} )



5. 소스 코드 형태로 존재하는 안드로이드 NDK 기본 라이브러리 사용하기


4번 경우와 유사한데 이 경우는 안드로이드 NDK 기본 라이브러리가 컴파일되지는 않고 소스 코드 형태로 존재한다는 점이 다릅니다. 사용법은 3번과 4번을 합친 형태입니다.


add_library( app-glue

             STATIC

             ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c )


target_link_libraries( native-lib

                       app-glue

                       ${log-lib} )



6. 이미 컴파일 된 외부 라이브러리를 불러와서 사용하기 (매우 중요)


현업에서 안드로이드 개발을 하다 보면 다른 사람이 만든 라이브러리를 이미 컴파일 된 상태로 불러와서 사용해야 할 경우가 정말 많습니다. 이 경우는 add_library()와 set_target_properties()를 사용해야 합니다. add_library()에서는 이 라이브러리가 이미 컴파일 된 상태라는 것을 알려주기 위해 IMPORTED를 사용하고, set_target_properties()에서는 컴파일 된 파일의 경로를 지정해줍니다. 여러가지 CPU 구조를 지원하려면 ANDROID_ABI 변수를 사용하면 됩니다. 컴파일 단계에서 헤더 파일 정보를 보려면 include_directories()를 사용하면 되고, 외부 라이브러리를 불러온 뒤에는 target_link_libraries()를 사용해서 원하는 라이브러리에 연동시키면 됩니다.


아래는 libimported-lib.so 파일을 불러와서 imported-lib 이라는 변수에 저장한 뒤에 native-lib에서 imported-lib을 다른 라이브러리와 함께 사용하는 예제입니다. PROPERTIES IMPORTED_LOCATION는 IMPORTED_LOCATION이라는 값을 정해주겠다는 이야기입니다.


add_library( imported-lib

             SHARED

             IMPORTED )


set_target_properties( imported-lib

                       PROPERTIES IMPORTED_LOCATION

                       imported-lib/src/${ANDROID_ABI}/libimported-lib.so )


include_directories( imported-lib/include/ )


target_link_libraries( native-lib imported-lib app-glue ${log-lib} )



이 정도면 안드로이드에서 일반적으로 CMake를 사용하는 데에는 큰 문제가 없을 것입니다.

[자바] JNI 시그니처 (Signiture)


JNI 작업을 엄청 하다가 갑자기 정리해놓고 싶어서 씁니다.

https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/types.html 에 있는 내용을 번역했습니다.


타입 시그니처


Z : 부울 값

B : 바이트

C : 문자

S : 쇼트 정수

I : 인트 정수

J : 롱 정수

F : 플로트 실수

D : 더블 실수

L : 클래스-전체-경로 ; 클래스

[ : 배열

( 인자들 ) 반환형 : 함수


예를 들어 다음의 자바 함수를 생각해 보겠습니다.


long f (int n, String s, int[] arr); 


이 함수의 시그니처는 다음과 같습니다.


(ILjava/lang/String;[I)J


---

(제가 추가한 내용)

I는 정수 n, Ljava/lang/String;은 문자열 s, [I는 정수 배열 arr이고 J는 반환값 long을 뜻합니다.


+ Recent posts