我的一畝三分地

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            2 隨筆 :: 14 文章 :: 3 評論 :: 0 Trackbacks
          http://tb.blog.csdn.net/TrackBack.aspx?PostId=910492

          一、去年曾經(jīng)做過一個JAVA和C通信的項目,用C語言實現(xiàn)某個特定功能函數(shù),然后在JAVA中調(diào)用。最近又有朋友問起,于是將做過的東西整理成學(xué)習(xí)筆記,希望對后來者有所幫助,呵呵。

          二、jni例子簡介

          jni-java native interface是java與其他語言本地通信的接口,按照jni的約定,java程序可以調(diào)用其他語言編寫的函數(shù),其他語言也可以調(diào)用java實現(xiàn)的方法,本文介紹了一個最簡單的java調(diào)用c方法的例子。主要由兩部分組成,

          一個是java主程序,另一個是被調(diào)用的dll(由C語言實現(xiàn))

          三、編寫步驟

          1、java主程序

          //文件testdll.java

          public class testdll
          {
          ??????? static
          ??????? {
          ?????????????? System.loadLibrary("goodluck");???? //goodluck為調(diào)用的庫名,不必加dll后綴
          ??????? } ?

          ??????? /*下面兩個函數(shù)為C語言實現(xiàn)的方法*/
          ??????? public native static int get();
          ??????? public native static void set(int i);

          ?????? //主函數(shù)
          ??????? public static void main(String[] args)
          ??????? {
          ??????????????? testdll test = new testdll();
          ??????????????? test.set(10);???????????????????????????????????????? //調(diào)用了在C中實現(xiàn)的方法set
          ??????????????? System.out.println(test.get());????????? //調(diào)用了在C中實現(xiàn)的方法get
          ??????????????? System.out.println("hello world!\n");
          ??????? }
          }

          2、得到C所需的頭文件

          ?執(zhí)行如下命令(假設(shè)jdk的安裝路徑為D:\Java\jdk1.5.0\bin)

          ????D:\Java\jdk1.5.0\bin\javac?? testdll.java???????????????????????????????????????? #生成testdll.class文件

          ?? D:\Java\jdk1.5.0\bin\javah?? testdll????????????????????????????????????????????????? #根據(jù)testdll.class生成testdll.h文件

          ?

          3、用c語言生成所需的dll

          (1)?打開vc6, 建立一個空的dll項目。

          ?????? 菜單里選"File"->New->Projects->Win32? dynamic link library,項目名為gookluck(與java文件中的調(diào)用庫名保持一致),第二步里選an empty DLL project.

          (2)把前面生成的testdll.h復(fù)制到這個項目中,再新添下面的testdll.cpp文件

          #include "testdll.h"

          int i = 0;
          JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass)
          {
          ??????? return i;
          }

          JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint j)
          {
          ???????? i = j;
          }

          此時編譯會報錯,因為還缺少幾個頭文件,因此要把下面兩個文件復(fù)制到項目目錄中或者vc的頭文件目錄 (即Microsoft Visual Studio\VC98\Include)中,jni.h文件和jni_md.h文件,在我機器這兩個文件原始目錄為

          D:\Java\jdk1.5.0\include\jni.h

          D:\Java\jdk1.5.0\include\win32\jni_md.h

          再次編譯,運行通過

          4、測試運行

          ??? 將3中得到的testdll.dll文件拷貝到testdll.class所在目錄下,執(zhí)行

          ????D:\Java\jdk1.5.0\bin\java testdll

          ??? 運行結(jié)果為

          ??? 10
          ??? hello world!

          ?? 說明調(diào)用正確。

          五、幾個注意事項

          1、System.loadLibrary("goodluck"); 一句,有時在別的情況下會報錯,主要原因是程序找不到這個庫文件所在的路徑,此時可以檢查path環(huán)境變量是否包含了合適的路徑,或者把dll文件拷貝到系統(tǒng)的dll目錄下,如C:\WINNT\system32下

          2、庫文件不必寫后綴名,寫了反而可能錯,因為這時程序會去找testdll.dll.dll文件,自然是不存在了:—)

          3、要調(diào)用的方法做本地聲明,關(guān)鍵字為native。并且只需要聲明,而不需要具體實現(xiàn)。如:
          ????? public native static void set(int i);
          ????? public native static int get();

          4、函數(shù)返回類型盡量用jni中的基本類型(如整型、字符等),最好不要返回自定義的類,那樣在c里有可能會引起錯誤。

          5、在c中寫具體實現(xiàn)的時候,我們只關(guān)心兩個函數(shù)原型

          JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass);


          JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint);

          這里JNIEXPORT都是JNI的關(guān)鍵字,表示此函數(shù)是要被java調(diào)用的,如果是其他語言調(diào)java語言,JNIEXPORT就要變成JNIIMPORT了。

          JNICALL告訴C編譯器參數(shù)進棧的方式,我們不必關(guān)心.

          jint是以JNI為中介使JAVA的int類型與本地c語言的int溝通的一種類型,我們就當(dāng)做int使用。其他類型名可以去查jni幫助文檔.

          函數(shù)的名稱是JAVA_再加上java程序的package路徑再加函數(shù)名組成的。

          參數(shù)中,我們也只需要關(guān)心在JAVA程序中存在的參數(shù),即第三個往后的參數(shù)。至于JNIEnv*和jclass我們一般沒有必要去碰它。

          知道這些約定后,我們沒有javah程序也可以自己手工寫出testdll.h文件來,不過麻煩些就是了^O^

          六、jni的其他參考資料

          jni屬于java語言的一部分,其權(quán)威資料自然要到sun的站點上查找(www.sun.com)

          以下是我在sun公司網(wǎng)站上找到的一些頁面

          http://java.sun.com/developer/onlineTraining/Programming/JDCBook/jniexamp.html

          給出了一個jni的例子,

          http://java.sun.com/j2se/1.4.2/docs/guide/jni/index.html

          給出了完整的jni介紹,

          另外,linux下jni的例子可以參見http://www.linuxmine.com/5629.html

          七、附j(luò)avah生成的testdll.h文件。

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

          #ifndef _Included_testdll
          #define _Included_testdll
          #ifdef __cplusplus
          extern "C" {
          #endif

          /*
          ?* Class:???? testdll
          ?* Method:??? get
          ?* Signature: ()I
          ?*/
          JNIEXPORT jint JNICALL Java_testdll_get
          ? (JNIEnv *, jclass);

          /*
          ?* Class:???? testdll
          ?* Method:??? set
          ?* Signature: (I)V
          ?*/
          JNIEXPORT void JNICALL Java_testdll_set
          ? (JNIEnv *, jclass, jint);

          #ifdef __cplusplus
          }
          #endif
          #endif

          posted on 2006-12-19 10:49 王某某 閱讀(623) 評論(0)  編輯  收藏 所屬分類: Java基礎(chǔ)
          主站蜘蛛池模板: 静安区| 丘北县| 栖霞市| 云林县| 浪卡子县| 满洲里市| 克什克腾旗| 北川| 隆尧县| 即墨市| 类乌齐县| 嘉定区| 彰武县| 石狮市| 义马市| 新龙县| 措美县| 二手房| 海晏县| 皮山县| 武山县| 吉林省| 唐山市| 林周县| 壤塘县| 牡丹江市| 金山区| 甘孜县| 宝山区| 尚义县| 县级市| 天门市| 丰镇市| 新邵县| 通化县| 东乡县| 龙川县| 子长县| 霍林郭勒市| 怀集县| 丁青县|