我的一畝三分地

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

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

          二、jni例子簡(jiǎn)介

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

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

          三、編寫步驟

          1、java主程序

          //文件testdll.java

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

          ??????? /*下面兩個(gè)函數(shù)為C語言實(shí)現(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中實(shí)現(xiàn)的方法set
          ??????????????? System.out.println(test.get());????????? //調(diào)用了在C中實(shí)現(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, 建立一個(gè)空的dll項(xiàng)目。

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

          (2)把前面生成的testdll.h復(fù)制到這個(gè)項(xiàng)目中,再新添下面的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;
          }

          此時(shí)編譯會(huì)報(bào)錯(cuò),因?yàn)檫€缺少幾個(gè)頭文件,因此要把下面兩個(gè)文件復(fù)制到項(xiàng)目目錄中或者vc的頭文件目錄 (即Microsoft Visual Studio\VC98\Include)中,jni.h文件和jni_md.h文件,在我機(jī)器這兩個(gè)文件原始目錄為

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

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

          再次編譯,運(yùn)行通過

          4、測(cè)試運(yùn)行

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

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

          ??? 運(yùn)行結(jié)果為

          ??? 10
          ??? hello world!

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

          五、幾個(gè)注意事項(xiàng)

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

          2、庫文件不必寫后綴名,寫了反而可能錯(cuò),因?yàn)檫@時(shí)程序會(huì)去找testdll.dll.dll文件,自然是不存在了:—)

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

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

          5、在c中寫具體實(shí)現(xiàn)的時(shí)候,我們只關(guān)心兩個(gè)函數(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ù)進(jìn)棧的方式,我們不必關(guān)心.

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

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

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

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

          六、jni的其他參考資料

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

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

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

          給出了一個(gè)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 王某某 閱讀(616) 評(píng)論(0)  編輯  收藏 所屬分類: Java基礎(chǔ)
          主站蜘蛛池模板: 本溪| 茶陵县| 万盛区| 麻阳| 韶山市| 临城县| 且末县| 寿光市| 泸定县| 华宁县| 略阳县| 荃湾区| 望都县| 阳高县| 绥化市| 海兴县| 青铜峡市| 广平县| 中宁县| 宜城市| 湖北省| 公主岭市| 镶黄旗| 富蕴县| 汶上县| 大化| 广水市| 浮山县| 邓州市| 吉木乃县| 文昌市| 永宁县| 乳山市| 麻江县| 大同市| 无极县| 瓦房店市| 佳木斯市| 景德镇市| 井冈山市| 驻马店市|