티스토리 뷰
정의
Java Native Interface 로 jvm 과 java 가 아닌 platform 의존적인 모든 native 언어로 구성된 라이브러리 사이에 정의된 인터페이스 입니다.
타입선언
자바에서 건네받은 변수를 C/C++에서 사용할 때, 자바에서 선언한 변수 타입에 따라 C/C++에서 변수를 사용하는 방법이 달라진다.
일반적으로 Java에서 사용하는 원시타입 앞에 j 를 붙이며, 배열의 경우 뒤에 Array를 붙인다.
Java | JNI(C/C++) | JNI(C/C++ 배열) |
boolean | jboolean | jbooleanArray |
byte | jbyte | jbyteArray |
char | jchar | jcharArray |
short | jshort | jshortArray |
int | jint | jintArray |
long | jlong | jlongArray |
float | jfloat | jfloatArray |
double | jdouble | jdoubleArray |
object | jobject | jobjectArray |
void | void |
시그니쳐
long foo(int n, String s, int[] arr); 을 signature 형태로 표시하면 다음과 같다.
(ILjava/lang/String;[I)J
시그니쳐를 해석해보면, J를 리턴하고, 인자는 I와 LJava/lang/String;과 [I 다.
이를 한번 더 해석하면 long을 리턴하고 인자는 int와 String과 int[]다.
그냥 JNI를 대충 따라하려 했을때, 가장 이해가 안되고 어려웠던게 바로 이 '시그니쳐' 였다.
시그니쳐는 호출하는 메소드명, 인수, 반환값을 말하며, 이를 지정하여 유일한 값을 만들때 사용한다.
원시타입은 알파벳 한글자로 표시한다. 예를 들어 byte는 B, boolean은 Z로 표시한다.(하단 테이블 설명)
클래스는 앞에는 L을, 끝에는 세미콜론(;)을 붙이고 클래스명을 쓸 땐 패키지명을 포함하여 FULL로 적는다.(fully-qualified-class라 한다) 이 때 패키지명의 .은 /로 대체하여 작성한다. 예를 들어 자바의 String타입은 Ljava/lang/String; 으로 표시한다.
배열은 앞에 [를 붙여서 표시한다. 예를 들어 int[]는 [I; 이다.(대문자 아이)
Java Type | Type Signature |
boolean | Z |
byte | B |
char | C |
short | S |
int | I |
long | J |
float | F |
double | D |
void | V |
fully-qualified-class | Lfully-qualified-class |
배열 | [Type |
리턴 타입 함수명 (인자) | (인자)리턴 타입 |
JAVA -> c++
java 에서 정의만 해둔다.
private native void funcname();
c++ 에서 아래와 같이 작성한다.
#ifdef __cplusplus
extern "C" {
#endif
void Java_com_company_puductname_classname_funcname(JNIEnv* env, jobject thisObj)
{
printf( "자바에서 C++ 함수를 호출했어요!!" );
}
#ifdef __cplusplus
}
#endif
c++ -> JAVA
int itemIndex = 13;
JniMethodInfo info;
JniHelper::getMethodInfo(info
, "com_company_puductname_classname"
, "funcname"
, "(I)V");
info.env->CallStaticVoidMethod(info.classID, info.methodID, itemIndex);
info.env->DeleteLocalRef(info.classID);