JHB의 프로그래밍 삽질기

[Android JNI/NDK] C/C++에서 Java 함수 호출 하기 / 멤버 변수 사용하기 본문

PROGRAMMING/Android/Java

[Android JNI/NDK] C/C++에서 Java 함수 호출 하기 / 멤버 변수 사용하기

roter 2015.09.21 01:03

JNI를 이용하여 C/C++에서 Java 함수를 호출 할 수 있다.

이때는 리플렉션을 이용한다. 개인적으로 Java를 처음 봤을 때 리플렉션 이런거 왜 존재하는 거야..하고 생각했었는데, 요즘 느끼는건 정말.. '강력하다'는 것이다. 웬만하면 변수명/함수명 등의 코드 이름으로 Java 내의 모든 기능을 다 이용 할 수 있으니.. 설계 관점에서 용이해진다. 물론 디버깅이나 가독성은 좀 떨어지는 감이 있지만..

 

C/C++에서 자바의 메소드를 호출하는 순서는 아래와 같다.

 

  1. FindClass 함수를 이용해서 Java의 클래스를 지정한다.
  2. 메소드명과 인자(시그니쳐)를 지정해서 클래스 내의 해당 메소드ID를 찾는다.
  3. 1,2에서 구한 클래스와 메소드를 이용하여 호출한다. 이때 반환값이나 정적/일반 메소드에 따라 메소드를 호출하는 방법이 다르다.

아래는 자바의 Integer클래스에 있는 parseInt 메소드를 호출해서 문자열을 int 타입의 숫자로 변환하는 네이티브 코드이다.

//인자로 jsting strInt를 받은 상태

jclass jklass = (*env)->FindClass(env, "java/lang/Integer"); //java.lang.Integer 클래스
jmethodId jmethod = (*env)->GetStaticMethodID(env, jklass, "parseInt", "(Ljava/lang/String;)I");
//static 메소드의 경우 위의 함수를 이용한다. 메소드명 "parseInt", 인자(시그니쳐) "(Ljava/lang/String;)I"
//일반 메소드의 경우 GetMethodID 함수를 이용한다.
if (jmethod == NULL) return;
jint val = (*env)->CallStaticIntMethod(env, jklass, jmethod, strInt);
//static 메소드를 call 하는 함수. 마지막의 strInt가 마치 자바에서 Integer.parseInt(strInt); 할때의 인자이다.

 

시그니쳐에 대한 자세한 설명은 JNI의 변수 타입과 시그니쳐(http://jhb.kr/315)를 참조하길 바란다.

 

위에서 찾은 메소드를 실행하기 위해서는 1. 반환값에 따라, 2.정적/일반 메소드 여부에 따라 호출하는 함수가 달라진다.

 

 반환값

일반 메소드 

 정적(static) 메소드

 Object

CallObjectMethod 

CallStaticObjectMethod 

 boolean

CallBooleanMethod

CallBooleanMethod

 byte

CallByteMethod

CallByteMethod

 char

CallCharMethod

CallCharMethod

 int

CallIntMethod

CallIntMethod

 long

CallLongMethod

CallLongMethod

 float

CallFloatMethod

CallFloatMethod

 double

CallDoubleMethod

CallDoubleMethod

 void

CallVoidMethod

CallVoidMethod

 

일반 메소드는 Call[반환Type]Method, 정적 메소드는 Call[반환Type]StaticMethod를 사용한다.

 

멤버 변수 역시 리플렉션을 통해 가져와서 사용 할 수 있다.

mCount라는 int 타입의 멤버 변수를 가져오는 코드는 아래와 같다.

jfieldID jfield = (*env)->GetFieldID(env, jklass, "mCount", "I");
if (jfield == NULL) return;
jint val = (*env)->GetIntField(env, jklass, jfield);

 

메소드 호출때와 비슷하게 Get[Type]Field 함수를 사용한다.

 

 

저작자 표시 비영리 변경 금지
신고
0 Comments
댓글쓰기 폼