走在架構(gòu)師的大道上 Jack.Wang's home

          Java, C++, linux c, C#.net 技術(shù),軟件架構(gòu),領(lǐng)域建模,IT 項(xiàng)目管理 Dict.CN 在線(xiàn)詞典, 英語(yǔ)學(xué)習(xí), 在線(xiàn)翻譯

          BlogJava 首頁(yè) 新隨筆 聯(lián)系 聚合 管理
            195 Posts :: 3 Stories :: 728 Comments :: 0 Trackbacks
           

                   JavaC++JNI編程小結(jié)
                                         --- jack 于湖大

           1.       什么是 JNI

              JNIJava Native Interface的縮寫(xiě)。從Java 1.1開(kāi)始,JNI標(biāo)準(zhǔn)成為java平臺(tái)的一部分,它允許Java和其他語(yǔ)言進(jìn)行交互。JNI一開(kāi)始為CC++而設(shè)計(jì)的,但是它并不妨礙你使用其他語(yǔ)言,只要調(diào)用約定受支持就可以了。

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

             關(guān)于 JNI 的用法很簡(jiǎn)單,有點(diǎn)像 java 里的 reflect 的工作機(jī)制,有興趣的朋友可以參看更詳細(xì)的書(shū)

          2.       JNI 開(kāi)發(fā)步驟

          l          編寫(xiě)帶有native聲明的方法的java類(lèi)

          l          使用javac IDE(JBuilder,eclipse)編譯所編寫(xiě)的java類(lèi)

          l          使用javah -jni java類(lèi)名生成擴(kuò)展名為h的頭文件

          l          使用C++ 實(shí)現(xiàn)本地方法,對(duì)調(diào)用簽名可用 javap –s –p [類(lèi)全名] 查看(開(kāi)發(fā) C++ 動(dòng)態(tài)鏈接庫(kù)本例是用的 VC6

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

          l          Java load 動(dòng)態(tài)鏈接庫(kù)文件,調(diào)用 native 方法

          3.       開(kāi)發(fā)實(shí)例

          1.        編寫(xiě) Java 類(lèi): (我的 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");

          }

          // 三個(gè) native 方法和一個(gè) int 變量

              public native boolean checkValid();

              public native void processData(BackgroundProcess bg);

              public native void processGarbage(String[] bg);

              public int num = 5;

              // C++ 中可以調(diào)用的方法

              public String backProcess(ArrayList<String> p) {

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

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

                  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();

                  // 調(diào)用 C++ DLL 中定義的方法。

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

                  bgP.processData(bgP);

                  bgP.processGarbage(array);

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

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

              }

          }

          2.        生成 C++ 的頭文件(javah 命令生成,用javap –s –p [類(lèi)全名] 命令查看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.        開(kāi)發(fā) C++ DLL 的原文件 (記得要加入 jni.h jni_md.h 兩個(gè)文件)

          發(fā)布 DLL 文件, 我是配置了 path 環(huán)境變量

          #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 << "數(shù)組大小是: " << 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.        現(xiàn)在你可以在 Java C++ 之間互調(diào)了

           





          本博客為學(xué)習(xí)交流用,凡未注明引用的均為本人作品,轉(zhuǎn)載請(qǐng)注明出處,如有版權(quán)問(wèn)題請(qǐng)及時(shí)通知。由于博客時(shí)間倉(cāng)促,錯(cuò)誤之處敬請(qǐng)諒解,有任何意見(jiàn)可給我留言,愿共同學(xué)習(xí)進(jìn)步。
          posted on 2008-03-02 08:23 Jack.Wang 閱讀(8941) 評(píng)論(4)  編輯  收藏 所屬分類(lèi): 開(kāi)發(fā)技術(shù)

          Feedback

          # re: Java與C++之JNI編程小結(jié) 2008-03-02 14:53 xifu
          田里影院  回復(fù)  更多評(píng)論
            

          # re: Java與C++之JNI編程小結(jié) 2008-03-03 12:29 Jack.Wang
          有問(wèn)題可以討論  回復(fù)  更多評(píng)論
            

          # re: Java與C++之JNI編程小結(jié) 2008-03-03 12:29 Jack.Wang
          @xifu
          什么意思  回復(fù)  更多評(píng)論
            

          # re: Java與C++之JNI編程小結(jié) 2008-03-07 11:52 rocket
          兩個(gè)OO語(yǔ)言寫(xiě)出來(lái)的process式方法。。。
          jack,寫(xiě)完你就不能用OO重構(gòu)一下嗎,呵呵  回復(fù)  更多評(píng)論
            

          主站蜘蛛池模板: 那坡县| 金沙县| 鹿邑县| 梨树县| 罗源县| 万载县| 水城县| 富阳市| 江西省| 贵州省| 临泽县| 威宁| 九龙坡区| 清新县| 延川县| 盘山县| 大丰市| 金坛市| 河间市| 五常市| 佳木斯市| 浪卡子县| 合山市| 五原县| 通道| 马龙县| 吴江市| 弥勒县| 松滋市| 公主岭市| 宝山区| 西乡县| 开原市| 都昌县| 青海省| 磴口县| 青岛市| 德庆县| 泸西县| 蒲城县| 南华县|