-자바에서, 객체의 변수에 접근하려면 그 객체의 이름과 변수의 이름을 알아야 한다. 마찬가지로 Native Method역시 자바 객체의 변수에 접근하기 위해서 그 객체의 타입과, 변수의 식별 정보를 컴퓨터에 인식시켜줄 필요가 있다.
※예를 들어 자바의 int형 데이터 타입의 변수에 접근하기 위해서는,Native Method에 자바의 객체 타입(클래스)과 변수의 식별 정보인 변수 이름과 변수 타입을 알려 주어야 한다.
FieldControl.java(맴버변수를 생성한 자바 소스 코드) |
public class FieldControl { int int_a = 10; double double_b = -1.2345; static { System.loadLibrary("control"); } public native double add(); public static void main(String[] args) throws Exception { double c = new FieldControl().add(); System.out.println("final result ==> a + b = " + c); } } |
C:\JavaExample\20> javac JavaObject.java C:\JavaExample\20> javah JavaObject |
-Native Method 내부에서 자바 객체의 변수에 접근하는 과정은 다음과 같이 세 단계로 나누어 진다.
-1단계: 자바 객체의 타입 알아오기
-2단계: 자바 객체의 타입에서 부터, 접근하려는 변수의 식별 정보를 알아오기
-3단계: 변수의 식별 정보를 사용해서, 원하는 객체의 실제 변수의 값을 변경하고 가져오기
자바에서 넘오는 객체의 타입은 두 가지 방법으로 알 수 있다.
-객체로 부터 그 타입을 알아내는 방법이다. 모든 Native Method가 첫 번째 매개 변수로 env라는 인터페이스 포인터를 갖는다는 것은 앞의 절에서 언급했다.
-이 인터페이스 포인터와 함께 모든 Native Method에게 주어지는 또 하나의 매개변수가 있다. 바로 jobject 타입의 obj라는 매개 변수이다. 모든 자바의 객체는 jobject라는 JNI가 미리 정의해 놓은 타입으로 표현 된다. Native Method에게 자동으로 넘겨지는 obj는 사실은 Native Method를 선언한 클래스의 객체 자신(this)이다. HelloWorld 예제의 경우라면 HelloWorld 객체 자신이 되겠군요. 다음의 함수사용해서 obj로 부터 객체의 타입을 알아 낼 수 있다. 그 원리는 리플렉션에서 getClass() 메서드를 이용해서 클래스의 정보를 클래스로더에게 알려주는 것과 똑 같다.
-jclass GetObjectClass(JNIEnv* env, jobject obj)
FieldControl.c(자바의 맴버변수를 조작하는 c언어의 소스 코드) |
#include <jni.h> #include "FieldControl.h" #include <stdio.h> JNIEXPORT jdouble JNICALL Java_FieldControl_add (JNIEnv *env, jobject obj){ double c; jclass class_fieldcontrol = (*env)->GetObjectClass(env, obj); jfieldID id_a = (*env)->GetFieldID(env, class_fieldcontrol, "int_a", "I"); jint a = (*env)->GetIntField(env,obj,id_a); jfieldID id_b = (*env)->GetFieldID(env, class_fieldcontrol, "double_b", "D"); jdouble b = (*env)->GetDoubleField(env,obj,id_b); printf("a : %d \n", a); printf("b : %f \n", b); c= a+b; printf("before ==> a + b = %f \n", a+b); a += 5; (*env)->SetIntField(env, obj, id_a, a); b += 2.123; (*env)->SetDoubleField(env, obj, id_b, b); c= a+b; printf("after ==> a + b = %f \n", a+b); return c; } |
C:\JavaExample\20>cl -Ic:\jdk1.3.1\include -Ic:\jdk1.3.1\include\win32 -LD F ieldControl.c -Fecontrol.dll …… FieldControl.c …… /dll /implib:control.lib /out:control.dll FieldControl.obj Creating library control.lib and object control.exp C:\JavaExample\object>java FieldControl a : 10 b : -1.234500 before ==> a + b = 8.765500 after ==> a + b = 15.888500 final result ==> a + b = 15.8885 |
GetFieldID()메서드 |
JfieldID GetFieldID (JNIEnv* env, jclass cls, const char name[], const char signal[]) : 주어진 jclass 에서 특정한 이름과 타입을 갖는 필드를 가져옵니다. 반환되는 값은 자바객체의 참조값이 입니다. jclass cls : Class 객체 const char name[] : 필드의 이름 const char signal[] : 필드의 타입 식별자 |
Signature |
Java Programming
Language Type |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fully-qualified-class |
|
type |
|
method type |
Set/Get<type>Field |
Set/GetBooleanField Set/GetByteField Set/GetCharField Set/GetDoubleField Set/GetFloatField Set/GetIntField Set/GetLongField Set/GetObjectField Set/GetShortField |
Static 변수를 조작하는 예 |
… jclass class_system = (*env)->FindClasS(env, "java/lang/System"); jfieldID id_out = (*env)->GetStaticFieldID(env, class_system, "out", "Ljava/io/PrintStream;"); jobject obj_out = (*env)->GetStaticObjectField(env, class_system, id_out); … |
'개발 언어 > JAVA' 카테고리의 다른 글
[JNI] 배열혈 아규먼트 (0) | 2011.07.22 |
---|---|
[jni]객체의 메서드 실행하기 (0) | 2011.07.22 |
[jni]문자열 전달 인자 (2) | 2011.07.22 |
[jni] 숫자 인자와 변환값 (0) | 2011.07.22 |
[JNI] 단계별 설명 (기본) (0) | 2011.07.22 |