C Code JNI 사용 (Class, 인수 사용등)

|

ShmData.java

 package SharedMemory;

public class ShmData{
    public int TagData;
    public int AnalogData;
    public String Comment;


    public void setTagData(int iTagData) { this.TagData = iTagData; }

    public void setAnalogData(int iAnalogData) { this.AnalogData = iAnalogData; }

    public void setComment(String strComment) { this.Comment = strComment; }

    public int getTagData() { return this.TagData; }

    public int getAnalogData() { return this.AnalogData; }

    public String getComment() { return this.Comment; }

}


이 같은 Java Class의 형식을 JNI를 이용하여 Return 하고자 할 경우 C Code File의 작성


JNIEXPORT jobject JNICALL Java_SharedMemory_MemoryRead_Data1

(JNIEnv *env, jobject obj, jint iIndex)

{

    int iTagData = 100;

    int iAnalogData = 1200;

    char strComment[100];

    memset(strComment, 0x00, sizeof(strComment));

    sprintf(strComment, "%s", "Jni Test !!");


    jclass targetClass;

    jmethodID mid;

    jobject newObject;

    jfieldID fid;

    jint result;

    jstring Comment;


    targetClass = (*env)->FindClass(env, "SharedMemory/ShmData");


    // 생성자 찾기

    mid = (*env)->GetMethodID(env, targetClass, "<init>", "()V");


    // 객체 생성(객체 레퍼런스 반환)

    newObject = (*env)->NewObject(env, targetClass, mid, "()V");


    // JniObject 객체의 intField 필드값 설정

    fid = (*env)->GetFieldID(env, targetClass, "TagData", "I");

    (*env)->SetIntField(env, newObject, fid, iTagData);


    fid = (*env)->GetFieldID(env, targetClass, "AnalogData", "I");

    (*env)->SetIntField(env, newObject, fid, iAnalogData );


    fid = (*env)->GetFieldID(env, targetClass, "Comment", "Ljava/lang/String;");

    Comment = (*env)->NewStringUTF(env, strComment);

    (*env)->SetObjectField(env, newObject, fid, Comment);


    return newObject;

위 Code는 JNI를 기반으로 한 C Code이다.

return형을 보자면 jobject 형이므로 Code안에서 return할 jobject newObject를 선언하였다.

그리고 java Code로는 class가 기준이 되므로 C와 java class를 연결할 jclass targetClass를 선언 하였다.


targetClass = (*env)->FindClass(env, "SharedMemory/ShmData");

SharedMemory/ShmData Class를 targetClass에 설정한다.


newObject = (*env)->NewObject(env, targetClass, mid, "()V");

newObject로 targetClass의 Instance를 생성하고 생성자를 실행한다.


fid = (*env)->GetFieldID(env, targetClass, "TagData", "I");

fid에 field(Class 변수)를 설정한다. 변수명은 TagData이고 Type는 I 즉 int Type이다.


(*env)->SetIntField(env, newObject, fid, iTagData);

설정된 Field에 값을 설정한다.


fid = (*env)->GetFieldID(env, targetClass, "Comment", "Ljava/lang/String;");

fid에 field(Class 변수)를 설정한다. 변수명은 Comment이고 Type는 Ljava/lang/String 즉 String Type이다.

Comment = (*env)->NewStringUTF(env, strComment);

jstring형으로 Data를 만들어 준다. c char 배열 또는 포인터 형과 java의 string의 관리 형태가 많이 다르기 때문에 이러한 형태를 취하는게 아닐까 싶다.


Instance에 값을 전부 설정했다면 return newObject를 하여 java에서 받을 수 있게 해준다.


위에서 주의 해야 할 것은 GetFieldID에서는 targetClass를 사용 하였지만 SetIntField 또는 SetObjectField시에는 NewObject 를 사용했다는 점이다.

Trackback 0 And Comment 1
  1. sdf 2017.09.06 15:24 address edit & del reply

    NewObject에 ()V 들어가지 않아요.
    그런건 메소드ID 얻어올때 넣어요