강좌 & 팁
JNI 에서는 클래스 내의 변수나 함수에 대한 접근도 가능하도록 인터페이스를 제공합니다.
우선 변수에 대한 접근에 대해 알아보겠습니다.
1. Field ID 구하기
java 객체내의 멤버 변수는 field ID 를 통해서 접근이 가능합니다.
JNIEXPORT void JNICALL Java_FieldControl_print (JNIEnv *env, jobject obj) { |
위 예제는 native 함수를 호출한 class 의 멤버 변수의 값을 출력하는 예제입니다.
호출한 객체 jobject obj 를 통해 해당 class의 정보를 구해오고, 그 class 내부의 각 멤버 변수들의 field id 를 구해오게 됩니다.
사용된 함수의 다음과 같이 선언되어 있습니다.
/usr/lib/jvm/java-6-openjdk/include/jni.h
jclass GetObjectClass(jobject obj);
jfieldID GetFieldID(jclass clazz, const char *name, const char *sig); |
GetFieldID 함수의 두번째 argument "name" 는 변수의 이름이고, "sig" 는 함수의 형을 나타내는 signature 문자열 입니다.
signature 규칙은 지난 시간에 JNI_OnLoad 에서 살펴본 규칙과 동일합니다.
http://forum.falinux.com/zbxe/?mid=lecture_tip&document_srl=573117
2. 변수 접근
변수의 값을 얻고, 넣을 수 있는 함수는 다음과 같습니다.
/usr/lib/jvm/java-6-openjdk/include/jni.h
jint GetIntField(jobject obj, jfieldID fieldID); void SetIntField(jobject obj, jfieldID fieldID, jint val) |
위 함수는 int 형에 대한 함수들이고 각 type 별로 별도의 함수들이 존재합니다.
중간에 Int 로 되어있는 부분만 바뀌면 되겠습니다.
유의해야 할 점은 field id 를 찾을 때는 jclass 가 필요하지만, 변수에 접근할 때는 jobject 가 다시 필요합니다.
class 의 선언은 하니이지남 객체는 여러 개 일 수 있으니깐, 당연하 것이라고 생각할 수 있을 것같습니다.
3. static 멤버의 접근
class 내의 static 멤버 변수에 대한 접근 함수가 별도로 존재합니다.
/usr/lib/jvm/java-6-openjdk/include/jni.h
jint GetStaticIntField(jclass clazz, jfieldID fieldID); void SetStaticIntField(jclass clazz, jfieldID fieldID, jint value); |
함수 이름 중간에 Static 이 붙어있기는 하지만 기본적인 사용법은 똑같습니다.
다만, static 멤버는 jclass 와 함께 접근하게 됩니다.
static 멤버는 class 객체보다는 class 자체를 통해 이용되므로, 이런 부분을 이해하면 당연한 것이라고 여겨집니다.
그 외에 멤버 변수가 배열이거나 객체인 경우에는 좀 더 복잡한 과정이 필요합니다.
하지만 이것들 또한 field id 를 통해 접근하게 되는 것은 동일하고,
지금까지 사용된 다른 함수들의 조합을 통해 이루어지는 과정이므로, 조금 더 익숙해지면 큰 어려움 없이 구현이 가능합니다.
이에 대한 부분은 다음에 예제를 통해 올리도록 하겠습니다.
안녕하세요.
저도 JNI와 씨름질하다가 잘 안돼서 그러는데요
JNI쪽에서 JAVA클래스의 BYTE멤버변수를 참조하려고 GetFieldID함수를 썼었는데... 아래와 같은 오유가 뜹니다.
도움 요청드립니다.개발도구는 NetBeans를 사용했습니다.
Exception in thread "main" java.lang.NoSuchFieldError: byTest
at FREngine.TestJNI.Function(Native Method)
at sample.Sample.main(Sample.java:24)
Java Result: 1
byTest는 멤버변수입니다.