1. 程式人生 > >JNI傳遞修改自定義Java Class陣列資料

JNI傳遞修改自定義Java Class陣列資料

結合前面講的2篇關於JNI的文章,這裡直接把程式碼貼上,主要是要知道如果傳遞自定義Class Array的時候,在JNI怎麼處理。單獨拎出來講解,是因為和系統自帶型別如long Array、String等的處理還是往往會有所區別的。可以做了寫程式碼時迷惑時的一個參考。

自定義POJO類

package com.testjni;

public class AObject
{
    int a;

    int b;

    public int getA()
    {
        return a;
    }

    public void setA(int a)
    {
        this.a = a;
    }

    public int getB()
    {
        return b;
    }

    public void setB(int b)
    {
        this.b = b;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String toString()
    {
        final StringBuilder sb =
            new StringBuilder("AObject").append('[').append("a=").append(a).append(",b=").append(b).append(']');
        return sb.toString();
    }
}

Java測試類

package com.testjni;

public class TestJNI
{
    public native boolean testJobjectArray(AObject[] aObjects);
    
    static
    {
        System.load("D:\\eclipseWebWorkSpace\\testest\\src\\com\\testjni\\libTestJNI_amd64.dll");
    }

    public static void main(String[] args)
    {
        TestJNI testJNI = new TestJNI();
        AObject[] aObjects = new AObject[3];
        for (int i = 0; i < 3; i++)
        {
            aObjects[i] = new AObject();
        }
        for (int i = 0; i < 3; i++)
        {
            System.out.println("aObjects[" + i + "]=" + aObjects[i]);
        }
        testJNI.testJobjectArray(aObjects);

        System.out.println("\n\n\nafter modified by jni");
        for (int i = 0; i < 10; i++)
        {
            System.out.println(i + "-->" + aObjects[i]);
        }
    }
}

JNI標頭檔案com_testjni_TestJNI.h

/* DO NOT EDIT THIS FILE - it is machine generated */
#include "jni.h"
/* Header for class com_testjni_TestJNI */

#ifndef _Included_com_testjni_TestJNI
#define _Included_com_testjni_TestJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_testjni_TestJNI
 * Method:    test_jobjectArray
 * Signature: ([Lcom/testjni/AObject;)Z
 */
JNIEXPORT jboolean JNICALL Java_com_testjni_TestJNI_testJobjectArray
  (JNIEnv *, jobject, jobjectArray);

#ifdef __cplusplus
}
#endif
#endif

JNI 原始碼檔案com_testjni_TestJNI.cpp

#include <stdio.h>
#include "com_testjni_TestJNI.h"
#include "jni.h"
static const char* const AObjectClassPath = "com/testjni/AObject";
JNIEXPORT jboolean JNICALL Java_com_testjni_TestJNI_testJobjectArray(JNIEnv *env, jobject obj, jobjectArray aObjects)
{
    jint arrLen = env->GetArrayLength(aObjects);
    printf("\narrLen=%d", nArrLen);

    jclass aObjectClass = env->FindClass(AObjectClassPath);
    if (aObjectClass == NULL)
    {
    	return true;
    }
    jfieldID afield = env->GetFieldID(aObjectClass, "a", "I");
    jfieldID bfield = env->GetFieldID(aObjectClass, "b", "I");

    for (int i = 0; i < 3; i++)
    {
        jobject aObject = env->GetObjectArrayElement(aObjects, i);
        env->SetIntField(aObject, afield, i*i);
        env->SetIntField(aObject, bfield, i*(i+1));
    }
}

編譯命令 cl /LD D:\eclipseWebWorkSpace\testest\src\com\testjni\com_testjni_TestJNI.cpp -o D:\eclipseWebWorkSpace\testest\src\com\testjni\libTestJNI_amd64.dll 執行結果: before modified by jni aObjects[0]=AObject[a=0,b=0] aObjects[1]=AObject[a=0,b=0] aObjects[2]=AObject[a=0,b=0]

after modified by jni aObjects[0]=AObject[a=0,b=0] aObjects[1]=AObject[a=1,b=2] aObjects[2]=AObject[a=4,b=6]

arrLen=3 關鍵的方法就是GetObjectArrayElement,取出jobjectArray中的元素,然後對這些自定義Class物件進行操作。