Todd

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            65 隨筆 :: 0 文章 :: 24 評論 :: 0 Trackbacks

          JNI 的類型和數(shù)據(jù)結構
          Java 類型  本地類型  說明
          boolean  jboolean  無符號,8 位
          byte     jbyte  無符號,8 位
          char     jchar  無符號,16 位
          short    jshort  有符號,16 位
          int      jint  有符號,32 位
          long     jlong  有符號,64 位
          float    jfloat  32 位
          double    jdouble  64 位
          void     void  N/A
          由于JVM中,使用統(tǒng)一的UTF-8編碼,java傳入的String參數(shù),在c文件中被jni轉換為jstring的數(shù)據(jù)類型,在c文件中聲明char* psz,然后psz = (char*)(*env)->GetStringUTFChars(env, jstring, NULL);c++的操作簡單些,env->GetStringUTFChars( jstring, NULL);注意使用完后,運行(*env)->ReleaseStringUTFChars(env, jstring, psz);
          將一個c的字符串轉為jstring,
          static char lastfile[80];

            JNIEXPORT jstring JNICALL Java_ReadFile_lastFile
              (JNIEnv *env, jobject jobj) {
               return((*env)->NewStringUTF(env, lastfile));
            }
          例子
          JNIEXPORT jstring JNICALL
          Java_Prompt_getLine(JNIEnv *env, jobject obj, jstring prompt)
          {
          char buf[128];
          const jbyte *str;
          str = (*env)->GetStringUTFChars(env, prompt, NULL);
          if (str == NULL) {
          return NULL; /* OutOfMemoryError already thrown */
          }
          printf("%s", str);
          (*env)->ReleaseStringUTFChars(env, prompt, str);
          /* We assume here that the user does not type more than
          * 127 characters */
          scanf("%s", buf);
          return (*env)->NewStringUTF(env, buf);
          }
          如果使用Unicode編碼,不需要使用UTF-8處理,使用如下方法
          JNIEXPORT jbyteArray JNICALL Java_ReadFile_loadFile
              (JNIEnv * env, jobject jobj, jstring name) {
                caddr_t m;
                jbyteArray jb;
                struct stat finfo;
                jboolean iscopy;
                const jchar *mfile = (*env)->GetStringChars(env,
            name, &iscopy);
            //...
                (*env)->ReleaseStringChars(env, name, mfile);
          傳遞Array
          boolean

           public static void setArray( boolean[] ba )
            {
              for( int i=0; i < ba.length; i++ )
                ba[i] = true;
              setArray0( ba );
            }

            private static native void setArray0( boolean[] ba );

          布爾型數(shù)組被初始化為 true,本地方法將把特定的元素設置為 false。同時,在 Java 源代碼中,我們可以更改 main 以使其包含測試代碼:

              boolean[] ba = new boolean[5];
              MyNative.setArray( ba );
              for( int i=0; i < ba.length; i++ )
                System.out.println( ba[i] );

          在編譯源代碼并執(zhí)行 javah 以后,MyNative.h 頭文件包含以下的原型:

          /*
           * Class:     MyNative
           * Method:    setArray0
           * Signature: ([Z)V
           */
          JNIEXPORT void JNICALL Java_MyNative_setArray0
            (JNIEnv *, jclass, jbooleanArray);

          布爾型數(shù)組是作為單個名為 jbooleanArray 的類型創(chuàng)建的。
          基本類型有它們自已的數(shù)組類型,如 jintArray 和 jcharArray。
          非基本類型的數(shù)組使用 jobjectArray 類型。下一個示例中包括一個 jobjectArray。這個布爾數(shù)組的數(shù)組元素是通過 JNI 方法 GetBooleanArrayElements 來訪問的。
          針對每種基本類型都有等價的方法。這個本地方法是如下實現(xiàn)的:

          JNIEXPORT void JNICALL Java_MyNative_setArray0
            (JNIEnv *env, jclass cls, jbooleanArray ba)
          {
            jboolean* pba = (*env)->GetBooleanArrayElements( env, ba, 0 );
            jsize len = (*env)->GetArrayLength(env, ba);
            int i=0;
            // 更改偶數(shù)數(shù)組元素
            for( i=0; i < len; i+=2 )
              pba[i] = JNI_FALSE;
            (*env)->ReleaseBooleanArrayElements( env, ba, pba, 0 );
          }

          指向布爾型數(shù)組的指針可以使用 GetBooleanArrayElements 獲得。
          數(shù)組大小可以用 GetArrayLength 方法獲得。使用 ReleaseBooleanArrayElements 方法釋放數(shù)組。就可以讀取和修改數(shù)組元素的值了。
          int 數(shù)組

          class IntArray {
              private native int sumArray(int[] arr);
              public static void main(String[] args) {
                  IntArray p = new IntArray();
                  int arr[] = new int[10];
                  for (int i = 0; i < 10; i++) {
                      arr[i] = i;
                  }
                  int sum = p.sumArray(arr);
                  System.out.println("sum = " + sum);
              }

              static {
                  System.loadLibrary("jnistudy");
              }
          }

          jni的c程序

          #include <jni.h>
          #include <stdio.h>
          #include "IntArray.h"

          JNIEXPORT jint JNICALL
          Java_IntArray_sumArray(JNIEnv *env, jobject obj, jintArray arr)
          {
              jint *carr;
              jint i, sum = 0;
              carr = (*env)->GetIntArrayElements(env, arr, NULL);
              if (carr == NULL) {
                  return 0; /* exception occurred */
              }

              for (i=0; i<10; i++) {
                  sum += carr[i];
              }

              (*env)->ReleaseIntArrayElements(env, arr, carr, 0);
              return sum;
          }

          GetIntArrayRegion得到數(shù)組,ReleaseIntArrayElements釋放資源,GetArrayLength得到數(shù)組的長度,SetIntArrayRegion修改數(shù)組元素的值。

          多位int 數(shù)組

          class ObjectArrayTest {
              private static native int[][] initInt2DArray(int size);
              public static void main(String[] args) {
                  int[][] i2arr = initInt2DArray(3);
                  for (int i = 0; i < 3; i++) {
                      for (int j = 0; j < 3; j++) {
                           System.out.print(" " + i2arr[i][j]);
                      }
                      System.out.println();
                  }
              }
              static {
                  System.loadLibrary("jnistudy");
              }
          }

          jni的代碼
          #include <jni.h>
          #include <stdio.h>
          #include "ObjectArrayTest.h"

          JNIEXPORT jobjectArray JNICALL
          Java_ObjectArrayTest_initInt2DArray(JNIEnv *env,
                                             jclass cls,
                                             jint size)
          {
              jobjectArray result;
              int i;
              jclass intArrCls = (*env)->FindClass(env, "[I");
              if (intArrCls == NULL) {
                  return NULL; /* exception thrown */
              }
              result = (*env)->NewObjectArray(env, size, intArrCls, NULL);
              if (result == NULL) {
                  return NULL; /* out of memory error thrown */
              }
              for (i = 0; i < size; i++) {
                  jint tmp[256];  /* make sure it is large enough! */
                  int j;
                  jintArray iarr = (*env)->NewIntArray(env, size);
                  if (iarr == NULL) {
                      return NULL; /* out of memory error thrown */
                  }
                  for (j = 0; j < size; j++) {
                      tmp[j] = i + j;
                  }
                  (*env)->SetIntArrayRegion(env, iarr, 0, size, tmp);
                  (*env)->SetObjectArrayElement(env, result, i, iarr);
                  (*env)->DeleteLocalRef(env, iarr);
              }
              return result;
          }
          Get/SetObjectArrayElement得到和設置數(shù)組的元素的值。
          傳遞 Java String 數(shù)組

          本例將通過最常用的非基本類型,Java String,說明如何訪問非基本對象的數(shù)組。字符串數(shù)組被傳遞給本地方法,而本地方法只是將它們顯示到控制臺上。
          MyNative 類定義中添加了以下幾個方法:

            public static void showStrings( String[] sa )
            {
              showStrings0( sa );
            }
            private static void showStrings0( String[] sa );

          測試
            String[] sa = new String[] { "Hello,", "world!", "JNI", "is", "fun." };
            MyNative.showStrings( sa );

          c代碼中,本地方法分別訪問每個元素,

          JNIEXPORT void JNICALL Java_MyNative_showStrings0
            (JNIEnv *env, jclass cls, jobjectArray sa)
          {
            int len = (*env)->GetArrayLength( env, sa );
            int i=0;
            for( i=0; i < len; i++ )
            {
              jobject obj = (*env)->GetObjectArrayElement(env, sa, i);
              jstring str = (jstring)obj;
              const char* szStr = (*env)->GetStringUTFChars( env, str, 0 );
              printf( "%s ", szStr );
              (*env)->ReleaseStringUTFChars( env, str, szStr );
            }
            printf( "\n" );
          }

          數(shù)組元素可以通過 GetObjectArrayElement 訪問。 因為返回值是 jstring 類型,所以可以安全地將它從 jobject 類型轉換為 jstring 類型。

          返回 Java String 數(shù)組
          在本地代碼中創(chuàng)建一個字符串數(shù)組并將它返回給 Java 調用者。MyNative.java 中添加了以下幾個方法:

            public static String[] getStrings()
            {
              return getStrings0();
            }
            private static native String[] getStrings0();

          使用showStrings 將 getStrings 的輸出顯示出來:

            MyNative.showStrings( MyNative.getStrings() );

          實現(xiàn)的本地方法返回五個字符串。

          JNIEXPORT jobjectArray JNICALL Java_MyNative_getStrings0
            (JNIEnv *env, jclass cls)
          {
            jstring      str;
            jobjectArray args = 0;
            jsize        len = 5;
            char*        sa[] = { "Hello,", "world!", "JNI", "is", "fun" };
            int          i=0;
            args = (*env)->NewObjectArray(env, len, (*env)->FindClass(env, "java/lang/String"), 0);
            for( i=0; i < len; i++ )
            {
              str = (*env)->NewStringUTF( env, sa[i] );
              (*env)->SetObjectArrayElement(env, args, i, str);
            }
            return args;
          }

          字符串數(shù)組是通過調用 NewObjectArray 創(chuàng)建的,同時傳遞了 String 類和數(shù)組長度兩個參數(shù)。Java String 是使用 NewStringUTF 創(chuàng)建的。String 元素是使用 SetObjectArrayElement 存入數(shù)組中的。


          另外要通過jni來改變java的參數(shù)引用,例如有參數(shù)jbyteArray account,修改完account的值后,java要獲取該值,直接使用
          jbyte* jbAccount = (env)->GetByteArrayElements(env, account, 0);
           char* szAccount = (char*)jbAccount;
          指針的地址并不是account的地址,最后賦下值才行
          env->SetByteArrayRegion(account,0,strlen(szAccount),jbyte* jbAccount);

          posted on 2009-11-24 15:03 Todd 閱讀(2002) 評論(0)  編輯  收藏 所屬分類: other

          只有注冊用戶登錄后才能發(fā)表評論。


          網站導航:
           
          主站蜘蛛池模板: 台东市| 威宁| 依兰县| 策勒县| 定襄县| 普兰县| 汝州市| 土默特右旗| 富顺县| 奈曼旗| 南漳县| 台江县| 娱乐| 平顶山市| 井研县| 南雄市| 广元市| 天水市| 永康市| 朝阳市| 赤壁市| 饶河县| 山阴县| 台东县| 镇远县| 赣州市| 东丽区| 汨罗市| 积石山| 资中县| 阳原县| 天全县| 太仆寺旗| 泸西县| 怀仁县| 泌阳县| 得荣县| 承德县| 蛟河市| 新干县| 金阳县|