走在架構師的大道上 Jack.Wang's home

          Java, C++, linux c, C#.net 技術,軟件架構,領域建模,IT 項目管理 Dict.CN 在線詞典, 英語學習, 在線翻譯

          BlogJava 首頁 新隨筆 聯系 聚合 管理
            195 Posts :: 3 Stories :: 728 Comments :: 0 Trackbacks
           

                   JavaC++JNI編程小結
                                         --- jack 于湖大

           1.       什么是 JNI

              JNIJava Native Interface的縮寫。從Java 1.1開始,JNI標準成為java平臺的一部分,它允許Java和其他語言進行交互。JNI一開始為CC++而設計的,但是它并不妨礙你使用其他語言,只要調用約定受支持就可以了。

                使用java與本地已編譯的代碼交互,通常會喪失平臺可移植性。但是,有些情況下這樣做是可以接受的,甚至是必須的,比如,使用一些舊的庫,與硬件、操作系統進行交互,或者為了提高程序的性能。

             關于 JNI 的用法很簡單,有點像 java 里的 reflect 的工作機制,有興趣的朋友可以參看更詳細的書

          2.       JNI 開發步驟

          l          編寫帶有native聲明的方法的java

          l          使用javac IDE(JBuilder,eclipse)編譯所編寫的java

          l          使用javah -jni java類名生成擴展名為h的頭文件

          l          使用C++ 實現本地方法,對調用簽名可用 javap –s –p [類全名] 查看(開發 C++ 動態鏈接庫本例是用的 VC6

          注意要從 JDK下面的 include 文件夾中把 jni.h jni_md.h 兩個文件 copy 到你的 VC 工程里

          l          Java load 動態鏈接庫文件,調用 native 方法

          3.       開發實例

          1.        編寫 Java : (我的 IDE eclipse)

          /**

           * Jack.Wang

           */

          package org.jm.jni;

          import java.util.ArrayList;

          /**

           * @author Jack.Wang

           * @time Mar 1, 2008

           */

          public class BackgroundProcess {

             static {

                  System.loadLibrary("org_jm_jni_BackgroundProcess");

          }

          // 三個 native 方法和一個 int 變量

              public native boolean checkValid();

              public native void processData(BackgroundProcess bg);

              public native void processGarbage(String[] bg);

              public int num = 5;

              // C++ 中可以調用的方法

              public String backProcess(ArrayList<String> p) {

                  System.out.println("這是 Java 里的方法,在 C++ 中調用。");

                  System.out.println("這個方法,是 java native checkValid 方法調用的。");

                  return "look up process ->" + p;

              }

              public static void main(String[] args) {

                  String[] array = new String[4];

                  array[0] = "jack";

                  array[1] = "maggie";

                  array[2] = "rocket";

                  array[3] = "tom";

                  BackgroundProcess bgP = new BackgroundProcess();

                  // 調用 C++ DLL 中定義的方法。

                  bgP.checkValid();// 該方法回調 java 中的 backProcess 方法

                  bgP.processData(bgP);

                  bgP.processGarbage(array);

                  // C++ DLL 改變了該變量

                  System.out.println("number 現在的值是: " + bgP.num);

              }

          }

          2.        生成 C++ 的頭文件(javah 命令生成,用javap –s –p [類全名] 命令查看java 方法簽名

          /* DO NOT EDIT THIS FILE - it is machine generated */

          #include "jni.h"

          /* Header for class org_jm_jni_BackgroundProcess */

          #ifndef _Included_org_jm_jni_BackgroundProcess

          #define _Included_org_jm_jni_BackgroundProcess

          #ifdef __cplusplus

          extern "C" {

          #endif

          /*

           * Class:     org_jm_jni_BackgroundProcess

           * Method:    checkValid

           * Signature: ()Z

           */

          JNIEXPORT jboolean JNICALL Java_org_jm_jni_BackgroundProcess_checkValid

           (JNIEnv *, jobject);

          /*

           * Class:     org_jm_jni_BackgroundProcess

           * Method:    processData

           * Signature: (Lorg/jm/jni/BackgroundProcess;)V

           */

          JNIEXPORT void JNICALL Java_org_jm_jni_BackgroundProcess_processData

           (JNIEnv *, jobject, jobject);

          /*

           * Class:     org_jm_jni_BackgroundProcess

           * Method:    processGarbage

           * Signature: ([Ljava/lang/String;)V

           */

          JNIEXPORT void JNICALL Java_org_jm_jni_BackgroundProcess_processGarbage

           (JNIEnv *, jobject, jobjectArray);

          #ifdef __cplusplus

          }

          #endif

          #endif

          3.        開發 C++ DLL 的原文件 (記得要加入 jni.h jni_md.h 兩個文件)

          發布 DLL 文件, 我是配置了 path 環境變量

          #include "org_jm_jni_BackgroundProcess.h"

          #include <iostream.h>

          #include <windows.h>

          #include "string.h"

          char* jstringTostring(JNIEnv* env, jstring jstr)

          {

                 char* rtn = NULL;

                 jclass clsstring = env->FindClass("java/lang/String");

                 jstring strencode = env->NewStringUTF("utf-8");

                 jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");

                 jbyteArray barr= (jbyteArray)env->CallObjectMethod(jstr, mid, strencode);

                 jsize alen = env->GetArrayLength(barr);

                 jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE);

                 if (alen > 0)

                 {

                           rtn = (char*)malloc(alen + 1);

                           memcpy(rtn, ba, alen);

                           rtn[alen] = 0;

                 }

                 env->ReleaseByteArrayElements(barr, ba, 0);

                 return rtn;

          }

          //char* to jstring

          jstring stoJstring(JNIEnv* env, const char* pat)

          {

                 jclass strClass = env->FindClass("Ljava/lang/String;");

                 jmethodID ctorID = env->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V");

                 jbyteArray bytes = env->NewByteArray(strlen(pat));

                 env->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte*)pat);

                 jstring encoding = env->NewStringUTF("utf-8");

                 return (jstring)env->NewObject(strClass, ctorID, bytes, encoding);

          }

          /*

          * Class:     org_jm_jni_BackgroundProcess

          * Method:    checkValid

          * Signature: ()Z

          */

          JNIEXPORT jboolean JNICALL Java_org_jm_jni_BackgroundProcess_checkValid

          (JNIEnv *env, jobject obj){

          jclass bgpClass=env->GetObjectClass(obj);

          jmethodID methodId=env->GetMethodID(bgpClass,"backProcess","(Ljava/util/ArrayList;)Ljava/lang/String;");

          jobject str=env->CallObjectMethod(obj,methodId,NULL);

          jfieldID fieldId=env->GetFieldID(bgpClass,"num","I");

          jint number=env->GetIntField(obj,fieldId);

          cout << "number 值是: " <<number << endl;

          env->SetIntField(obj,fieldId,100L);

          return 1;    

          }

          /*

          * Class:     org_jm_jni_BackgroundProcess

          * Method:    processData

          * Signature: (Lorg/jm/jni/BackgroundProcess;)V

          */

          JNIEXPORT void JNICALL Java_org_jm_jni_BackgroundProcess_processData

          (JNIEnv *env, jobject, jobject){

          cout<< "this function do nothing " << endl;

          }

          /*

          * Class:     org_jm_jni_BackgroundProcess

          * Method:    processGarbage

          * Signature: ([Ljava/lang/String;)V

          */

          JNIEXPORT void JNICALL Java_org_jm_jni_BackgroundProcess_processGarbage

          (JNIEnv *env, jobject, jobjectArray array){

          jint size=env->GetArrayLength(array);

          cout << "數組大小是: " << size << endl;

          jstring tempObj=NULL;

              char *pszSTR1 = NULL;

          for(int i=0;i<size;i++){

                     cout << "current value is : " << i << endl;

                     tempObj=(jstring)env->GetObjectArrayElement(array,i);

                     const char * chars =env->GetStringUTFChars(tempObj, 0); 

              cout << chars << endl; 

             }

          }

          4.        現在你可以在 Java C++ 之間互調了

           





          本博客為學習交流用,凡未注明引用的均為本人作品,轉載請注明出處,如有版權問題請及時通知。由于博客時間倉促,錯誤之處敬請諒解,有任何意見可給我留言,愿共同學習進步。
          posted on 2008-03-02 08:23 Jack.Wang 閱讀(8932) 評論(4)  編輯  收藏 所屬分類: 開發技術

          Feedback

          # re: Java與C++之JNI編程小結 2008-03-02 14:53 xifu
          田里影院  回復  更多評論
            

          # re: Java與C++之JNI編程小結 2008-03-03 12:29 Jack.Wang
          有問題可以討論  回復  更多評論
            

          # re: Java與C++之JNI編程小結 2008-03-03 12:29 Jack.Wang
          @xifu
          什么意思  回復  更多評論
            

          # re: Java與C++之JNI編程小結 2008-03-07 11:52 rocket
          兩個OO語言寫出來的process式方法。。。
          jack,寫完你就不能用OO重構一下嗎,呵呵  回復  更多評論
            

          主站蜘蛛池模板: 漯河市| 榆林市| 嘉禾县| 白玉县| 宝丰县| 迁安市| 鹤壁市| 阜新| 望江县| 大冶市| 巍山| 金寨县| 新安县| 武冈市| 菏泽市| 金川县| 兴业县| 太和县| 东光县| 祁连县| 岗巴县| 无棣县| 肇东市| 吉林省| 巴里| 田林县| 渑池县| 巴马| 千阳县| 石城县| 永靖县| 兰溪市| 宜川县| 阿拉善右旗| 句容市| 蓝山县| 延安市| 康乐县| 顺平县| 铁岭县| 莆田市|