經典的java/android下JNI編程教程

【教程一】JAVA JNI簡介:
    Java 本機接口(Java Native Interface (JNI))是一個本機編程接口,它是 Java 軟件開發工具箱(Java SoftwareDevelopment Kit (SDK))的一部分,JNI它提供了若干的API,實現了和Java和其他語言的通信(主要是C&C++)。

    JNI允許Java代碼使用以其它語言(譬如 C  C++)編寫的代碼和代碼庫。

    Invocation APIJNI的一部分)可以用來將Java虛擬機(JVM)嵌入到本機應用程序中,從而允許程序員從本機代碼內部調用Java 代碼。

    也許不少人覺得Java已經足夠強大,爲什麼要需要JNI這種東西呢?

    我們知道Java是一種平臺無關性的語言,平臺對於上層的java代碼來說是透明的,所以在多數時間我們是不需要JNI的,但是假如你遇到了如下的三種情況之一呢? 

   1.你的Java代碼,需要得到一個文件的屬性。但是你找遍了JDK幫助文檔也找不到相關的API 

   2.在本地還有一個別的系統,不過他不是Java語言實現的,這個時候你的老闆要求你把兩套系統整合到一起。 

   3.你的Java代碼中需要用到某種算法,不過算法是用C實現並封裝在動態鏈接庫文件(DLL)當中的。 

對於上述的三種情況,如果沒有JNI的話,那就會變得異常棘手了。就算找到解決方案了,也是費時費力。其實說到底還是會增加開發和維護的成本。 

二、環境需求

JNI 最常見的兩個應用:Java程序調用C/C++,以及從C/C++程序調用Java代碼

1、需要下列工具與組件:
    javac.exe  Java 編譯器:隨 SDKJava 2 SDK及以上) 一起提供的 。

    java.exe   Java 虛擬機(JVM):隨 SDK 一起提供的 。

    javah.exe  本機方法 C 文件生成器:隨 SDK 一起提供的 。

2、定義JNI的庫文件和本機頭文件:
    jni.h 頭文件)、jvm.lib  jvm.dll window下)或 libjvm.so 文件(linux下),這些文件都是隨 SDK 一起提供的。

3、能夠創建共享庫的 C  C++ 編譯器。

最常見的兩個 C 編譯器是用於WindowsVisual C++和用於基於UNIX系統的 gcc/cc

因此,後面我們將會介紹在兩種環境下的JNI編程例子。

 

 

教程二windowsjava JNI編程技巧——JAVA調用c/c++(0)

一、使用情況

    當無法用Java語言編寫整個應用程序時,JNI允許您使用本機代碼。

    在下列典型情況下,您可能決定使用本機代碼:
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

    1、希望用更低級、更快的編程語言去實現對時間有嚴格要求的代碼。

    2、希望從 Java 程序訪問舊代碼或代碼庫。

    3、需要標準 Java 類庫中不支持的依賴於平臺的特性。

二、所需軟件

    eclipse3.4.1JDK6VC6.0

三、步驟分析

 Java 程序調用 C  C ++ 代碼的過程由六個步驟組成:

我們將在下面幾頁中深入討論每個步驟,但還是先讓我們迅速地瀏覽一下它們:

1、編寫 Java 代碼。

    我們將從編寫 Java 類開始,這些類執行三個任務:

    1)聲明將要調用的本機方法;

    2)裝入包含本機代碼的共享庫;

    3)然後調用該本機方法。

2、編譯 Java 代碼。

    在使用 Java 類之前,必須成功地將它們編譯成字節碼。

3、創建C/C++頭文件。
    C/C++頭文件將聲明想要調用的本機函數說明。
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

    然後,這個頭文件與 C/C++ 函數實現(請參閱步驟 4)一起來創建共享庫(請參閱步驟 5)。

4、編寫 C/C++ 代碼。
   這一步實現 C  C++ 源代碼文件中的函數。
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

   C/C++ 源文件必須包含步驟 3 中創建的頭文件。

5、創建共享庫文件。
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

   從步驟 4 中創建的C源代碼文件來創建共享庫文件。

6、運行 Java 程序。
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

   運行該代碼,並查看它是否有用。我們還將討論一些用於解決常見錯誤的技巧。

 

【教程三】windowsjava JNI編程技巧——JAVA調用c/c++(1)

步驟 1:編寫 Java 代碼
我們從編寫 Java 源代碼文件開始,它將聲明本機方法(或方法),裝入包含本機代碼的共享庫,然後實際調用本機方法。

這裏是名爲JNI_javaCallc_test

直接使用文本編輯器或在ecilpos中建立工程敲入以下代碼:

[cpp] view plaincopy

<!--[if !supportLists]-->1.   <!--[endif]-->package test;  

<!--[if !supportLists]-->2.   <!--[endif]-->  

<!--[if !supportLists]-->3.   <!--[endif]-->public class JNI_javaCallc_test {  

<!--[if !supportLists]-->4.   <!--[endif]-->      

<!--[if !supportLists]-->5.   <!--[endif]-->    //c/c++本地方法  

<!--[if !supportLists]-->6.   <!--[endif]-->    public native int intMethod(int n);  

<!--[if !supportLists]-->7.   <!--[endif]-->      

<!--[if !supportLists]-->8.   <!--[endif]-->    public native boolean booleanMethod(boolean bool);  

<!--[if !supportLists]-->9.   <!--[endif]-->      

<!--[if !supportLists]-->10.  <!--[endif]-->    public native String stringMethod(String text);  

<!--[if !supportLists]-->11.  <!--[endif]-->      

<!--[if !supportLists]-->12.  <!--[endif]-->    public native int intArrayMethod(int[] intArray);  

<!--[if !supportLists]-->13.  <!--[endif]-->      

<!--[if !supportLists]-->14.  <!--[endif]-->    //java main方法  

<!--[if !supportLists]-->15.  <!--[endif]-->    public static void main(String[] args){  

<!--[if !supportLists]-->16.  <!--[endif]-->        //包含c語言動態庫  

<!--[if !supportLists]-->17.  <!--[endif]-->        System.loadLibrary("test_JNI_javaCallc_test");  

<!--[if !supportLists]-->18.  <!--[endif]-->          

<!--[if !supportLists]-->19.  <!--[endif]-->        JNI_javaCallc_test sample = new JNI_javaCallc_test();  

<!--[if !supportLists]-->20.  <!--[endif]-->          

<!--[if !supportLists]-->21.  <!--[endif]-->        int square = sample.intMethod(5);  

<!--[if !supportLists]-->22.  <!--[endif]-->          

<!--[if !supportLists]-->23.  <!--[endif]-->        boolean bool = sample.booleanMethod(true);  

<!--[if !supportLists]-->24.  <!--[endif]-->          

<!--[if !supportLists]-->25.  <!--[endif]-->        String text =sample.stringMethod("JAVA");  

<!--[if !supportLists]-->26.  <!--[endif]-->            

<!--[if !supportLists]-->27.  <!--[endif]-->        int sum = sample.intArrayMethod(new int[] { 1, 1, 2, 3, 5, 8, 13 });  

<!--[if !supportLists]-->28.  <!--[endif]-->          

<!--[if !supportLists]-->29.  <!--[endif]-->        System.out.println("intMethod: " + square);  

<!--[if !supportLists]-->30.  <!--[endif]-->          

<!--[if !supportLists]-->31.  <!--[endif]-->        System.out.println("booleanMethod: " + bool);  

<!--[if !supportLists]-->32.  <!--[endif]-->          

<!--[if !supportLists]-->33.  <!--[endif]-->        System.out.println("stringMethod: " + text);  

<!--[if !supportLists]-->34.  <!--[endif]-->          

<!--[if !supportLists]-->35.  <!--[endif]-->        System.out.println("intArrayMethod: " + sum);  

<!--[if !supportLists]-->36.  <!--[endif]-->    }  

<!--[if !supportLists]-->37.  <!--[endif]-->}  

這段代碼做了些什麼?
    
首先,請注意對 native 關鍵字的使用,它只能隨方法一起使用。

    native 關鍵字告訴 Java 編譯器:方法是用 Java 類之外的本機代碼實現的,但其聲明卻在Java 中。只能在 Java 類中聲明本機方法,而不能實現它(但是不能聲明爲抽象的方法,使用native關鍵字即可),所以本機方法不能擁有方法主體。

現在,讓我們逐行研究一下代碼:

從第 6 行到第 12 行,我們聲明瞭四個 native 方法。
在第 17 行,我們裝入了包含這些本機方法的實現的共享庫文件。(到步驟 5 時,我們將創建該共享庫文件。)
最終,從第 21 行到第 27 行,我們調用了本機方法。
注:這個操作和調用非本機 Java 方法的操作沒有差異。

 

 

【教程四】windowsjava JNI編程技巧——JAVA調用c/c++(2)

步驟 2:編譯 Java 代碼

接下來,我們需要將 Java 代碼編譯成字節碼。

完成這一步的方法之一是使用隨SDK一起提供的Java編譯器javac

用來將 Java 代碼編譯成字節碼的命令是:

cd test
javac JNI_javaCallc_test.java

    如果是在eclipse環境下編寫的以上代碼,文件保存時會自動在工程目錄的bin下生成以上java文件

步驟 3:創建 C/C++ 頭文件

第三步是創建 C/C++ 頭文件,它定義本機函數說明。

完成這一步的方法之一是使用 javah.exe,它是隨 SDK 一起提供的本機方法 C 存根生成器工具。

這個工具被設計成用來創建頭文件,該頭文件爲在 Java 源代碼文件中所找到的每個 native 方法定義 C 風格的函數。

這裏使用的命令是: 
cd test
javah -classpath . test.JNI_javaCallc_test

注意.test之間有空格

會生成以下文件:

[cpp] view plaincopy

<!--[if !supportLists]-->1.     <!--[endif]--><span style="font-family:SimSun;font-size:16px;">/* DO NOT EDIT THIS FILE - it is machine generated */  

<!--[if !supportLists]-->2.     <!--[endif]-->#include <jni.h>  

<!--[if !supportLists]-->3.     <!--[endif]-->/* Header for class test_JNI_javaCallc_test */  

<!--[if !supportLists]-->4.     <!--[endif]-->  

<!--[if !supportLists]-->5.     <!--[endif]-->#ifndef _Included_test_JNI_javaCallc_test  

<!--[if !supportLists]-->6.     <!--[endif]-->#define _Included_test_JNI_javaCallc_test  

<!--[if !supportLists]-->7.     <!--[endif]-->#ifdef __cplusplus  

<!--[if !supportLists]-->8.     <!--[endif]-->extern "C" {  

<!--[if !supportLists]-->9.     <!--[endif]-->#endif  

<!--[if !supportLists]-->10.  <!--[endif]-->/* 

<!--[if !supportLists]-->11.  <!--[endif]--> * Class:     test_JNI_javaCallc_test 

<!--[if !supportLists]-->12.  <!--[endif]--> * Method:    intMethod 

<!--[if !supportLists]-->13.  <!--[endif]--> * Signature: (I)I 

<!--[if !supportLists]-->14.  <!--[endif]--> */  

<!--[if !supportLists]-->15.  <!--[endif]-->JNIEXPORT jint JNICALL Java_test_JNI_1javaCallc_1test_intMethod  

<!--[if !supportLists]-->16.  <!--[endif]-->  (JNIEnv *, jobject, jint);  

<!--[if !supportLists]-->17.  <!--[endif]-->  

<!--[if !supportLists]-->18.  <!--[endif]-->/* 

<!--[if !supportLists]-->19.  <!--[endif]--> * Class:     test_JNI_javaCallc_test 

<!--[if !supportLists]-->20.  <!--[endif]--> * Method:    booleanMethod 

<!--[if !supportLists]-->21.  <!--[endif]--> * Signature: (Z)Z 

<!--[if !supportLists]-->22.  <!--[endif]--> */  

<!--[if !supportLists]-->23.  <!--[endif]-->JNIEXPORT jboolean JNICALL Java_test_JNI_1javaCallc_1test_booleanMethod  

<!--[if !supportLists]-->24.  <!--[endif]-->  (JNIEnv *, jobject, jboolean);  

<!--[if !supportLists]-->25.  <!--[endif]-->  

<!--[if !supportLists]-->26.  <!--[endif]-->/* 

<!--[if !supportLists]-->27.  <!--[endif]--> * Class:     test_JNI_javaCallc_test 

<!--[if !supportLists]-->28.  <!--[endif]--> * Method:    stringMethod 

<!--[if !supportLists]-->29.  <!--[endif]--> * Signature: (Ljava/lang/String;)Ljava/lang/String; 

<!--[if !supportLists]-->30.  <!--[endif]--> */  

<!--[if !supportLists]-->31.  <!--[endif]-->JNIEXPORT jstring JNICALL Java_test_JNI_1javaCallc_1test_stringMethod  

<!--[if !supportLists]-->32.  <!--[endif]-->  (JNIEnv *, jobject, jstring);  

<!--[if !supportLists]-->33.  <!--[endif]-->  

<!--[if !supportLists]-->34.  <!--[endif]-->/* 

<!--[if !supportLists]-->35.  <!--[endif]--> * Class:     test_JNI_javaCallc_test 

<!--[if !supportLists]-->36.  <!--[endif]--> * Method:    intArrayMethod 

<!--[if !supportLists]-->37.  <!--[endif]--> * Signature: ([I)I 

<!--[if !supportLists]-->38.  <!--[endif]--> */  

<!--[if !supportLists]-->39.  <!--[endif]-->JNIEXPORT jint JNICALL Java_test_JNI_1javaCallc_1test_intArrayMethod  

<!--[if !supportLists]-->40.  <!--[endif]-->  (JNIEnv *, jobject, jintArray);  

<!--[if !supportLists]-->41.  <!--[endif]-->  

<!--[if !supportLists]-->42.  <!--[endif]-->#ifdef __cplusplus  

<!--[if !supportLists]-->43.  <!--[endif]-->}  

<!--[if !supportLists]-->44.  <!--[endif]-->#endif  

<!--[if !supportLists]-->45.  <!--[endif]-->#endif<strong>  

<!--[if !supportLists]-->46.  <!--[endif]--></strong></span>  


關於 C/C++ 頭文件

    如您可能已經注意到的那樣,JNI_javaCallc_test.h 中的 C/C++ 函數說明和JNI_javaCallc_test.java 中的 Java native 方法聲明有很大差異。

1JNIEXPORT  JNICALL 是用於導出函數的、依賴於編譯器的指示符。 

2、返回類型、參數類型是映射到 Java 類型的 C/C++ 類型,比如:jstringjint

現在來介紹下JNI裏的數據類型:

C++裏,編譯器會很據所處的平臺來爲一些基本的數據類型來分配長度,因此也就造成了平臺不一致性,而這個問題在Java中則不存在,因爲有JVM的緣故,所以Java中的基本數據類型在所有平臺下得到的都是相同的長度,比如int的寬度永遠都是32位。基於這方面的原因,javac++的基本數據類型就需要實現一些mapping,保持一致性。

下面的表可以概括:下標列舉了常見的c/c++到到java的類型映射表。

    Java類型           

           本地類型             

    JNI中定義的別名         

int

long

jint

long

_int64

jlong

byte

signed char

jbyte

boolean

unsigned char

jboolean

char

unsigned short

jchar

short

short

jshort

float

float

jfloat

double

double

jdouble

Object

_jobject*

jobject


JNI的設計者其實已經幫我們取好了相應的別名以方便記憶。如果想了解一些更加細緻的信息,可以去看一些jni.h這個頭文件,各種數據類型的定義以及別名就被定義在這個文件中。

除了 Java 聲明中的一般參數以外,所有這些函數的參數表中都有一個指向 JNIEnv  jobject 的指針。

指向 JNIEnv 的指針實際上是一個指向函數指針表的指針。

正如將要在步驟中看到的,這些函數提供各種用來在CC++中操作Java數據的能力。

jobject 參數引用當前對象

因此,如果CC++代碼需要引用Java函數,則這個jobject充當引用或指針,返回調用的 Java 對象。

函數名本身是由前綴“Java_”加全限定類名,再加下劃線和方法名構成的。

 

【教程五】windowsjava JNI編程技巧——JAVA調用c/c++(3)

 

步驟 4:編寫 C/C++ 代碼

    當談到編寫 C/C++ 函數實現時,有一點需要牢記:說明必須和 JNI_javaCallc_test.h 的函數聲明完全一樣。

    我們將研究用於 C 實現和 C++ 實現的完整代碼,然後討論兩者之間的差異。

C函數實現
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

以下是 JNI_javaCallc_test.c,它是用 C 編寫的實現:

[cpp] view plaincopy

<!--[if !supportLists]-->1.     <!--[endif]-->#include <jni.h>  

<!--[if !supportLists]-->2.     <!--[endif]-->/* Header for class test_JNI_javaCallc_test */  

<!--[if !supportLists]-->3.     <!--[endif]-->  

<!--[if !supportLists]-->4.     <!--[endif]-->  

<!--[if !supportLists]-->5.     <!--[endif]-->/* 

<!--[if !supportLists]-->6.     <!--[endif]--> * Class:     test_JNI_javaCallc_test 

<!--[if !supportLists]-->7.     <!--[endif]--> * Method:    intMethod 

<!--[if !supportLists]-->8.     <!--[endif]--> * Signature: (I)I 

<!--[if !supportLists]-->9.     <!--[endif]--> */  

<!--[if !supportLists]-->10.  <!--[endif]-->JNIEXPORT jint JNICALL Java_test_JNI_1javaCallc_1test_intMethod(JNIEnv *env, jobject obj, jint num)  

<!--[if !supportLists]-->11.  <!--[endif]--> {  

<!--[if !supportLists]-->12.  <!--[endif]-->    return num * num;  

<!--[if !supportLists]-->13.  <!--[endif]--> }  

<!--[if !supportLists]-->14.  <!--[endif]-->    

<!--[if !supportLists]-->15.  <!--[endif]-->/* 

<!--[if !supportLists]-->16.  <!--[endif]--> * Class:     test_JNI_javaCallc_test 

<!--[if !supportLists]-->17.  <!--[endif]--> * Method:    booleanMethod 

<!--[if !supportLists]-->18.  <!--[endif]--> * Signature: (Z)Z 

<!--[if !supportLists]-->19.  <!--[endif]--> */  

<!--[if !supportLists]-->20.  <!--[endif]-->JNIEXPORT jboolean JNICALL Java_test_JNI_1javaCallc_1test_booleanMethod  

<!--[if !supportLists]-->21.  <!--[endif]-->  (JNIEnv *env, jobject obj, jboolean boolean) {  

<!--[if !supportLists]-->22.  <!--[endif]-->   return!boolean;  

<!--[if !supportLists]-->23.  <!--[endif]-->}  

<!--[if !supportLists]-->24.  <!--[endif]-->/* 

<!--[if !supportLists]-->25.  <!--[endif]--> * Class:     test_JNI_javaCallc_test 

<!--[if !supportLists]-->26.  <!--[endif]--> * Method:    stringMethod 

<!--[if !supportLists]-->27.  <!--[endif]--> * Signature: (Ljava/lang/String;)Ljava/lang/String; 

<!--[if !supportLists]-->28.  <!--[endif]--> */  

<!--[if !supportLists]-->29.  <!--[endif]-->JNIEXPORT jstring JNICALL Java_test_JNI_1javaCallc_1test_stringMethod  

<!--[if !supportLists]-->30.  <!--[endif]-->  (JNIEnv *env, jobject obj, jstring string)   

<!--[if !supportLists]-->31.  <!--[endif]-->  {  

<!--[if !supportLists]-->32.  <!--[endif]-->    const char *str = (*env)->GetStringUTFChars(env, string, 0);  

<!--[if !supportLists]-->33.  <!--[endif]-->    char cap[128];  

<!--[if !supportLists]-->34.  <!--[endif]-->    strcpy(cap, str);  

<!--[if !supportLists]-->35.  <!--[endif]-->    (*env)->ReleaseStringUTFChars(env, string, str);  

<!--[if !supportLists]-->36.  <!--[endif]-->    return (*env)->NewStringUTF(env, strupr(cap));  

<!--[if !supportLists]-->37.  <!--[endif]-->}  

<!--[if !supportLists]-->38.  <!--[endif]-->  

<!--[if !supportLists]-->39.  <!--[endif]-->/* 

<!--[if !supportLists]-->40.  <!--[endif]--> * Class:     test_JNI_javaCallc_test 

<!--[if !supportLists]-->41.  <!--[endif]--> * Method:    intArrayMethod 

<!--[if !supportLists]-->42.  <!--[endif]--> * Signature: ([I)I 

<!--[if !supportLists]-->43.  <!--[endif]--> */  

<!--[if !supportLists]-->44.  <!--[endif]-->JNIEXPORT jint JNICALL Java_test_JNI_1javaCallc_1test_intArrayMethod  

<!--[if !supportLists]-->45.  <!--[endif]-->  (JNIEnv *env, jobject obj, jintArray array)   

<!--[if !supportLists]-->46.  <!--[endif]-->  {  

<!--[if !supportLists]-->47.  <!--[endif]-->    int i, sum = 0;  

<!--[if !supportLists]-->48.  <!--[endif]-->    jsize len = (*env)->GetArrayLength(env, array);  

<!--[if !supportLists]-->49.  <!--[endif]-->    jint*body = (*env)->GetIntArrayElements(env, array, 0);  

<!--[if !supportLists]-->50.  <!--[endif]-->    for(i=0; i<len; i++)  

<!--[if !supportLists]-->51.  <!--[endif]-->    {   sum += body[i];  

<!--[if !supportLists]-->52.  <!--[endif]-->    }  

<!--[if !supportLists]-->53.  <!--[endif]-->    (*env)->ReleaseIntArrayElements(env, array, body, 0);  

<!--[if !supportLists]-->54.  <!--[endif]-->    return sum;  

<!--[if !supportLists]-->55.  <!--[endif]-->}  

 

C++ 函數實現

[cpp] view plaincopy

<!--[if !supportLists]-->1.     <!--[endif]-->#include <jni.h>  

<!--[if !supportLists]-->2.     <!--[endif]-->/* Header for class test_JNI_javaCallc_test */  

<!--[if !supportLists]-->3.     <!--[endif]-->  

<!--[if !supportLists]-->4.     <!--[endif]-->  

<!--[if !supportLists]-->5.     <!--[endif]-->/* 

<!--[if !supportLists]-->6.     <!--[endif]--> * Class:     test_JNI_javaCallc_test 

<!--[if !supportLists]-->7.     <!--[endif]--> * Method:    intMethod 

<!--[if !supportLists]-->8.     <!--[endif]--> * Signature: (I)I 

<!--[if !supportLists]-->9.     <!--[endif]--> */  

<!--[if !supportLists]-->10.  <!--[endif]-->JNIEXPORT jint JNICALL Java_test_JNI_1javaCallc_1test_intMethod(JNIEnv *env, jobject obj, jint num)  

<!--[if !supportLists]-->11.  <!--[endif]--> {  

<!--[if !supportLists]-->12.  <!--[endif]-->    return num * num;  

<!--[if !supportLists]-->13.  <!--[endif]--> }  

<!--[if !supportLists]-->14.  <!--[endif]-->    

<!--[if !supportLists]-->15.  <!--[endif]-->/* 

<!--[if !supportLists]-->16.  <!--[endif]--> * Class:     test_JNI_javaCallc_test 

<!--[if !supportLists]-->17.  <!--[endif]--> * Method:    booleanMethod 

<!--[if !supportLists]-->18.  <!--[endif]--> * Signature: (Z)Z 

<!--[if !supportLists]-->19.  <!--[endif]--> */  

<!--[if !supportLists]-->20.  <!--[endif]-->JNIEXPORT jboolean JNICALL Java_test_JNI_1javaCallc_1test_booleanMethod  

<!--[if !supportLists]-->21.  <!--[endif]-->  (JNIEnv *env, jobject obj, jboolean boolean) {  

<!--[if !supportLists]-->22.  <!--[endif]-->   return!boolean;  

<!--[if !supportLists]-->23.  <!--[endif]-->}  

<!--[if !supportLists]-->24.  <!--[endif]-->/* 

<!--[if !supportLists]-->25.  <!--[endif]--> * Class:     test_JNI_javaCallc_test 

<!--[if !supportLists]-->26.  <!--[endif]--> * Method:    stringMethod 

<!--[if !supportLists]-->27.  <!--[endif]--> * Signature: (Ljava/lang/String;)Ljava/lang/String; 

<!--[if !supportLists]-->28.  <!--[endif]--> */  

<!--[if !supportLists]-->29.  <!--[endif]-->JNIEXPORT jstring JNICALL Java_test_JNI_1javaCallc_1test_stringMethod  

<!--[if !supportLists]-->30.  <!--[endif]-->  (JNIEnv *env, jobject obj, jstring string)   

<!--[if !supportLists]-->31.  <!--[endif]-->  {  

<!--[if !supportLists]-->32.  <!--[endif]-->    constchar *str = env->GetStringUTFChars(string, 0);  

<!--[if !supportLists]-->33.  <!--[endif]-->    char cap[128];  

<!--[if !supportLists]-->34.  <!--[endif]-->    strcpy(cap, str);  

<!--[if !supportLists]-->35.  <!--[endif]-->    env->ReleaseStringUTFChars(string, str);  

<!--[if !supportLists]-->36.  <!--[endif]-->    returnenv->NewStringUTF(strupr(cap));  

<!--[if !supportLists]-->37.  <!--[endif]-->}  

<!--[if !supportLists]-->38.  <!--[endif]-->  

<!--[if !supportLists]-->39.  <!--[endif]-->/* 

<!--[if !supportLists]-->40.  <!--[endif]--> * Class:     test_JNI_javaCallc_test 

<!--[if !supportLists]-->41.  <!--[endif]--> * Method:    intArrayMethod 

<!--[if !supportLists]-->42.  <!--[endif]--> * Signature: ([I)I 

<!--[if !supportLists]-->43.  <!--[endif]--> */  

<!--[if !supportLists]-->44.  <!--[endif]-->JNIEXPORT jint JNICALL Java_test_JNI_1javaCallc_1test_intArrayMethod  

<!--[if !supportLists]-->45.  <!--[endif]-->  (JNIEnv *env, jobject obj, jintArray array)   

<!--[if !supportLists]-->46.  <!--[endif]-->  {  

<!--[if !supportLists]-->47.  <!--[endif]-->     int i,sum = 0;  

<!--[if !supportLists]-->48.  <!--[endif]-->     jsizelen = env->GetArrayLength(array);  

<!--[if !supportLists]-->49.  <!--[endif]-->     jint*body = env->GetIntArrayElements(array, 0);  

<!--[if !supportLists]-->50.  <!--[endif]-->     for(i=0; i<len; i++)  

<!--[if !supportLists]-->51.  <!--[endif]-->     {     

<!--[if !supportLists]-->52.  <!--[endif]-->        sum += body[i];  

<!--[if !supportLists]-->53.  <!--[endif]-->     }  

<!--[if !supportLists]-->54.  <!--[endif]-->    env->ReleaseIntArrayElements(array, body, 0);  

<!--[if !supportLists]-->55.  <!--[endif]-->     returnsum;  

<!--[if !supportLists]-->56.  <!--[endif]-->}  

 

 C++ 函數實現的比較
唯一的差異在於用來訪問 JNI 函數的方法。

C中,JNI 函數調用由“(*env)->”作前綴,目的是爲了取出函數指針所引用的值。

 C++ 中,JNIEnv 類擁有處理函數指針查找的內聯成員函數。

下面將說明這個細微的差異,其中,這兩行代碼訪問同一函數,但每種語言都有各自的語法

C語法:    jsize len = (*env)->GetArrayLength(env,array);

C++語法:  jsize len =env->GetArrayLength(array);

 

 

【教程六】windowsjava JNI編程技巧——JAVA調用c/c++(4)

步驟 5:創建共享庫文件

接下來,我們創建包含本機代碼的共享庫文件。

大多數 C  C++ 編譯器除了可以創建機器代碼可執行文件以外,也可以創建共享庫文件。

用來創建共享庫文件的命令取決於您使用的編譯器。

下面是在 Windows執行的命令。

Windows

使用visual studio commandprompt工具cl.exe

cl -I"C:\Program Files\Java\jdk1.6.0_10\include" -I"C:\Program Files\Java\jdk1.6.0_10\include\win32" -LD test_JNI_javaCallc_test.c -Fe test_JNI_javaCallc_test.dll

也可以使用vc6.0直接建立動態庫

<!--[if !vml]--><!--[endif]-->

<!--[if !vml]--><!--[endif]-->

<!--[if !vml]--><!--[endif]-->

 

編譯的時候需要jni相關的頭文件和庫文件,在vc6.0的的搜索路徑加入與java有關的兩個路徑即可即可

Tools->sptions->Directories

<!--[if !vml]--><!--[endif]-->

 

Linux:使用gcc工具
gcc -c -fPIC -I/usr/java/jdk1.6.0_22/include/ -I/usr/java/jdk1.6.0_22/include/linux/ Sample1.c
gcc -shared -fPIC -o libSample1.so Sample1.o

步驟 6:運行 Java 程序
最後一步是運行 Java 程序,並確保代碼正確工作。

因爲必須在 Java 虛擬機中執行所有 Java 代碼,所以需要使用 Java 運行時環境。

完成這一步的方法之一是使用 java,它是隨 SDK 一起提供的 Java 解釋器。

所使用的命令是:

java -cp . test.test_JNI_javaCallc_test

或者直接在eclipose中運行即可

輸出:
intMethod: 25
booleanMethod: false
stringMethod: JAVA
intArrayMethod: 33

 

【教程七】 C/C++ 程序調用 Java 代碼

JNI允許您從本機代碼內調用 Java 類方法。

要做到這一點,通常必須使用 Invocation API 在本機代碼內創建和初始化一個 JVM

下列是您可能決定從 C/C++ 代碼調用Java 代碼的典型情況:

    1.希望實現的這部分代碼是平臺無關的,它將用於跨多種平臺使用的功能。

    2.需要在本機應用程序中訪問用 Java 語言編寫的代碼或代碼庫。

    3.希望從本機代碼利用標準 Java 類庫。

C/C++ 程序調用 Java代碼的四個步驟:
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

1.編寫 Java 代碼。

    這個步驟包含編寫一個或多個 Java 類,這些類實現(或調用其它方法實現)您想要訪問的功能。

2.編譯 Java 代碼。

    在能夠使用這些 Java 類之前,必須成功地將它們編譯成字節碼。

3.編寫 C/C++ 代碼。

    這個代碼將創建和實例化 JVM,並調用正確的 Java 方法。

4.運行本機 C/C++ 應用程序。

    將運行應用程序以查看它是否正常工作。我們還將討論一些用於處理常見錯誤的技巧。

步驟 1:編寫Java 代碼
我們從編寫一個或多個 Java 源代碼文件開始,這些文件將實現我們想要本機 C/C++ 代碼使用的功能。
下面顯示了一個 Java 代碼示例JNI_cCalljava_test.java
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

[java] view plaincopy

<!--[if !supportLists]-->1.     <!--[endif]-->package test;  

<!--[if !supportLists]-->2.     <!--[endif]-->  

<!--[if !supportLists]-->3.     <!--[endif]-->public class JNI_cCalljava_test {  

<!--[if !supportLists]-->4.     <!--[endif]-->      

<!--[if !supportLists]-->5.     <!--[endif]-->   public static int intMethod(int n) {  

<!--[if !supportLists]-->6.     <!--[endif]-->          return n*n;  

<!--[if !supportLists]-->7.     <!--[endif]-->      }  

<!--[if !supportLists]-->8.     <!--[endif]-->  

<!--[if !supportLists]-->9.     <!--[endif]-->    public static boolean booleanMethod(boolean bool) {  

<!--[if !supportLists]-->10.  <!--[endif]-->     return !bool;  

<!--[if !supportLists]-->11.  <!--[endif]-->    }  

<!--[if !supportLists]-->12.  <!--[endif]-->      

<!--[if !supportLists]-->13.  <!--[endif]-->}  

注:JNI_cCalljava_test.java 實現了兩個 static Java 方法:intMethod(intn) booleanMethod(boolean bool)(分別在第 3 行和第 7 行)。static方法是一種不需要與對象實例關聯的類方法。調用 static方法要更容易些,因爲不必實例化對象來調用它們。

步驟 2:編譯Java 代碼
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

接下來,我們將 Java 代碼編譯成字節碼。

完成這一步的方法之一是使用隨SDK 一起提供的Java 編譯器 javac。使用的命令是:

JNI_cCalljava_test.java

或者直接在eclipose中編寫保存即可

步驟 3:編寫 C/C++ 代碼

即使是在本機應用程序中運行,所有 Java 字節碼也必須在 JVM 中執行。

因此 C/C++ 應用程序必須包含用來創建和初始化 JVM 的調用。

爲了方便我們,SDK 包含了作爲共享庫文件(jvm.dll  jvm.so)的 JVM,這個庫文件可以嵌入到本機應用程序中。

 

讓我們先從瀏覽一下 C  C++ 應用程序的整個代碼開始,然後對兩者進行比較。
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

帶有嵌入式 JVM C 應用程序:

[cpp] view plaincopy

<!--[if !supportLists]-->1.     <!--[endif]-->#include <jni.h>  

<!--[if !supportLists]-->2.     <!--[endif]-->//jni.h文件包含在 C 代碼中所需要的 JNI 的所有類型和函數定義  

<!--[if !supportLists]-->3.     <!--[endif]-->#ifdef _WIN32  

<!--[if !supportLists]-->4.     <!--[endif]-->#define PATH_SEPARATOR ';'  

<!--[if !supportLists]-->5.     <!--[endif]-->#else  

<!--[if !supportLists]-->6.     <!--[endif]-->#define PATH_SEPARATOR ':'  

<!--[if !supportLists]-->7.     <!--[endif]-->#endif  

<!--[if !supportLists]-->8.     <!--[endif]-->//1.包括準備本機應用程序以處理 Java 代碼  

<!--[if !supportLists]-->9.     <!--[endif]-->//2. JVM 嵌入本機應用程序  

<!--[if !supportLists]-->10.  <!--[endif]-->//3.然後從該應用程序內找到並調用 Java 方法。  

<!--[if !supportLists]-->11.  <!--[endif]-->int main()  

<!--[if !supportLists]-->12.  <!--[endif]-->{  

<!--[if !supportLists]-->13.  <!--[endif]-->/* 

<!--[if !supportLists]-->14.  <!--[endif]-->接下來,聲明所有希望在程序中使用的變量。 

<!--[if !supportLists]-->15.  <!--[endif]-->JavaVMOption options[] 具有用於 JVM 的各種選項設置。 

<!--[if !supportLists]-->16.  <!--[endif]-->當聲明變量時,確保所聲明的JavaVMOption options[] 數組足夠大,以便能容納您希望使用的所有選項。 

<!--[if !supportLists]-->17.  <!--[endif]-->在本例中,我們使用的唯一選項就是類路徑選項。 

<!--[if !supportLists]-->18.  <!--[endif]-->因爲在本示例中,我們所有的文件都在同一目錄中,所以將類路徑設置成當前目錄。 

<!--[if !supportLists]-->19.  <!--[endif]-->可以設置類路徑,使它指向任何您希望使用的目錄結構。*/  

<!--[if !supportLists]-->20.  <!--[endif]-->    JavaVMOption options[1];  

<!--[if !supportLists]-->21.  <!--[endif]-->    JNIEnv *env;  

<!--[if !supportLists]-->22.  <!--[endif]-->    JavaVM *jvm;  

<!--[if !supportLists]-->23.  <!--[endif]-->    JavaVMInitArgs vm_args;  

<!--[if !supportLists]-->24.  <!--[endif]-->/*JNIEnv *env          表示 JNI 執行環境。 

<!--[if !supportLists]-->25.  <!--[endif]-->JavaVM jvm             是指向 JVM 的指針,我們主要使用這個指針來創建、初始化和銷燬 JVM 

<!--[if !supportLists]-->26.  <!--[endif]-->JavaVMInitArgs vm_args 表示可以用來初始化 JVM 的各種 JVM 參數。*/  

<!--[if !supportLists]-->27.  <!--[endif]-->      

<!--[if !supportLists]-->28.  <!--[endif]-->    long status;  

<!--[if !supportLists]-->29.  <!--[endif]-->    jclass cls;  

<!--[if !supportLists]-->30.  <!--[endif]-->    jmethodID mid;  

<!--[if !supportLists]-->31.  <!--[endif]-->    jint square;  

<!--[if !supportLists]-->32.  <!--[endif]-->    jboolean not;  

<!--[if !supportLists]-->33.  <!--[endif]-->  

<!--[if !supportLists]-->34.  <!--[endif]-->/*avaVMInitArgs 結構表示用於 JVM 的初始化參數。 

<!--[if !supportLists]-->35.  <!--[endif]-->在執行 Java 代碼之前,可以使用這些參數來定製運行時環境。 

<!--[if !supportLists]-->36.  <!--[endif]-->正如您所見,這些選項是一個參數, Java 版本是另一個參數。 

<!--[if !supportLists]-->37.  <!--[endif]-->按如下所示設置了這些參數:*/  

<!--[if !supportLists]-->38.  <!--[endif]-->  

<!--[if !supportLists]-->39.  <!--[endif]-->/* JVM 設置類路徑,以使它能找到所需要的 Java 類。 

<!--[if !supportLists]-->40.  <!--[endif]-->在這個特定示例中,因爲 Sample2.class Sample2.exe 都位於同一目錄中,所以將類路徑設置成當前目錄。 

<!--[if !supportLists]-->41.  <!--[endif]-->我們用來爲 Sample2.c 設置類路徑的代碼如下所示:*/  

<!--[if !supportLists]-->42.  <!--[endif]-->    options[0].optionString = "-Djava.class.path=.";  

<!--[if !supportLists]-->43.  <!--[endif]-->    memset(&vm_args, 0, sizeof(vm_args));  

<!--[if !supportLists]-->44.  <!--[endif]-->    vm_args.version = JNI_VERSION_1_2;  

<!--[if !supportLists]-->45.  <!--[endif]-->    vm_args.nOptions = 1;  

<!--[if !supportLists]-->46.  <!--[endif]-->    vm_args.options = options;  

<!--[if !supportLists]-->47.  <!--[endif]-->      

<!--[if !supportLists]-->48.  <!--[endif]-->/*創建 JVM 

<!--[if !supportLists]-->49.  <!--[endif]-->處理完所有設置之後,現在就準備創建 JVM 了。先從調用方法開始 

<!--[if !supportLists]-->50.  <!--[endif]-->如果成功,則這個方法返回零,否則,如果無法創建 JVM,則返回JNI_ERR*/  

<!--[if !supportLists]-->51.  <!--[endif]-->    status = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);  

<!--[if !supportLists]-->52.  <!--[endif]-->  

<!--[if !supportLists]-->53.  <!--[endif]-->    if (status != JNI_ERR)  

<!--[if !supportLists]-->54.  <!--[endif]-->    {  

<!--[if !supportLists]-->55.  <!--[endif]-->/* 

<!--[if !supportLists]-->56.  <!--[endif]-->查找並裝入 Java  

<!--[if !supportLists]-->57.  <!--[endif]-->一旦創建了 JVM 之後,就可以準備開始在本機應用程序中運行 Java 代碼。 

<!--[if !supportLists]-->58.  <!--[endif]-->首先,需要使用FindClass() 函數查找並裝入 Java 類,如下所示: 

<!--[if !supportLists]-->59.  <!--[endif]-->cls 變量存儲執行FindClass() 函數後的結果,如果找到該類,則 cls 變量表示該Java 類的句柄, 

<!--[if !supportLists]-->60.  <!--[endif]-->如果不能找到該類,則 cls 將爲零。 

<!--[if !supportLists]-->61.  <!--[endif]-->*/  

<!--[if !supportLists]-->62.  <!--[endif]-->        cls = (*env)->FindClass(env, "test/JNI_cCalljava_test");  

<!--[if !supportLists]-->63.  <!--[endif]-->        printf("test1,cls=%d...\n",cls);  

<!--[if !supportLists]-->64.  <!--[endif]-->  

<!--[if !supportLists]-->65.  <!--[endif]-->        if(cls !=0)  

<!--[if !supportLists]-->66.  <!--[endif]-->        {   

<!--[if !supportLists]-->67.  <!--[endif]-->/* 

<!--[if !supportLists]-->68.  <!--[endif]-->查找 Java 方法 

<!--[if !supportLists]-->69.  <!--[endif]-->接下來,我們希望用 GetStaticMethodID() 函數在該類中查找某個方法。 

<!--[if !supportLists]-->70.  <!--[endif]-->我們希望查找方法 intMethod,它接收一個 int 參數並返回一個 int 

<!--[if !supportLists]-->71.  <!--[endif]-->以下是查找 intMethod 的代碼: 

<!--[if !supportLists]-->72.  <!--[endif]-->*/  

<!--[if !supportLists]-->73.  <!--[endif]-->            mid = (*env)->GetStaticMethodID(env, cls, "intMethod""(I)I");  

<!--[if !supportLists]-->74.  <!--[endif]-->/* 

<!--[if !supportLists]-->75.  <!--[endif]-->mid 變量存儲執行 GetStaticMethodID() 函數後的結果。 

<!--[if !supportLists]-->76.  <!--[endif]-->如果找到了該方法,則 mid 變量表示該方法的句柄。 

<!--[if !supportLists]-->77.  <!--[endif]-->如果不能找到該方法,則mid 將爲零。 

<!--[if !supportLists]-->78.  <!--[endif]-->*/  

<!--[if !supportLists]-->79.  <!--[endif]-->            if(mid !=0)  

<!--[if !supportLists]-->80.  <!--[endif]-->            {   

<!--[if !supportLists]-->81.  <!--[endif]-->/*CallStaticIntMethod() 方法接受 cls(表示類)、mid(表示方法)以及用於該方法一個或多個參數。 

<!--[if !supportLists]-->82.  <!--[endif]-->在本例中參數是 int 5*/  

<!--[if !supportLists]-->83.  <!--[endif]-->                square = (*env)->CallStaticIntMethod(env, cls, mid, 5);  

<!--[if !supportLists]-->84.  <!--[endif]-->                printf("Result of intMethod: %d\n", square);  

<!--[if !supportLists]-->85.  <!--[endif]-->            }  

<!--[if !supportLists]-->86.  <!--[endif]-->  

<!--[if !supportLists]-->87.  <!--[endif]-->            mid = (*env)->GetStaticMethodID(env, cls, "booleanMethod""(Z)Z");  

<!--[if !supportLists]-->88.  <!--[endif]-->            if(mid !=0)  

<!--[if !supportLists]-->89.  <!--[endif]-->            {  

<!--[if !supportLists]-->90.  <!--[endif]-->                not = (*env)->CallStaticBooleanMethod(env, cls, mid, 1);  

<!--[if !supportLists]-->91.  <!--[endif]-->                printf("Result of booleanMethod: %d\n", not);  

<!--[if !supportLists]-->92.  <!--[endif]-->            }  

<!--[if !supportLists]-->93.  <!--[endif]-->        }  

<!--[if !supportLists]-->94.  <!--[endif]-->  

<!--[if !supportLists]-->95.  <!--[endif]-->        (*jvm)->DestroyJavaVM(jvm);  

<!--[if !supportLists]-->96.  <!--[endif]-->        return 0;  

<!--[if !supportLists]-->97.  <!--[endif]-->    }  

<!--[if !supportLists]-->98.  <!--[endif]-->    else  

<!--[if !supportLists]-->99.  <!--[endif]-->    return -1;  

<!--[if !supportLists]-->100.  <!--[endif]-->}  


<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

帶有嵌入式 JVM C++ 應用程序
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

[cpp] view plaincopy

<!--[if !supportLists]-->1.     <!--[endif]-->#include <jni.h>  

<!--[if !supportLists]-->2.     <!--[endif]-->  

<!--[if !supportLists]-->3.     <!--[endif]-->#ifdef _WIN32  

<!--[if !supportLists]-->4.     <!--[endif]-->#define PATH_SEPARATOR ';'  

<!--[if !supportLists]-->5.     <!--[endif]-->#else  

<!--[if !supportLists]-->6.     <!--[endif]-->#define PATH_SEPARATOR ':'  

<!--[if !supportLists]-->7.     <!--[endif]-->#endif  

<!--[if !supportLists]-->8.     <!--[endif]-->  

<!--[if !supportLists]-->9.     <!--[endif]-->int main()  

<!--[if !supportLists]-->10.  <!--[endif]-->{  

<!--[if !supportLists]-->11.  <!--[endif]-->    JavaVMOption options[1];  

<!--[if !supportLists]-->12.  <!--[endif]-->    JNIEnv *env;  

<!--[if !supportLists]-->13.  <!--[endif]-->    JavaVM *jvm;  

<!--[if !supportLists]-->14.  <!--[endif]-->    JavaVMInitArgs vm_args;  

<!--[if !supportLists]-->15.  <!--[endif]-->    long status;  

<!--[if !supportLists]-->16.  <!--[endif]-->    jclass cls;  

<!--[if !supportLists]-->17.  <!--[endif]-->    jmethodID mid;  

<!--[if !supportLists]-->18.  <!--[endif]-->    jint square;  

<!--[if !supportLists]-->19.  <!--[endif]-->    jboolean not;  

<!--[if !supportLists]-->20.  <!--[endif]-->  

<!--[if !supportLists]-->21.  <!--[endif]-->    options[0].optionString = "-Djava.class.path=.";  

<!--[if !supportLists]-->22.  <!--[endif]-->    memset(&vm_args, 0, sizeof(vm_args));  

<!--[if !supportLists]-->23.  <!--[endif]-->    vm_args.version = JNI_VERSION_1_2;  

<!--[if !supportLists]-->24.  <!--[endif]-->    vm_args.nOptions = 1;  

<!--[if !supportLists]-->25.  <!--[endif]-->    vm_args.options = options;  

<!--[if !supportLists]-->26.  <!--[endif]-->    status = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);  

<!--[if !supportLists]-->27.  <!--[endif]-->  

<!--[if !supportLists]-->28.  <!--[endif]-->    if (status != JNI_ERR)  

<!--[if !supportLists]-->29.  <!--[endif]-->    {  

<!--[if !supportLists]-->30.  <!--[endif]-->        cls = env->FindClass("Sample2");  

<!--[if !supportLists]-->31.  <!--[endif]-->        if(cls !=0)  

<!--[if !supportLists]-->32.  <!--[endif]-->        {     

<!--[if !supportLists]-->33.  <!--[endif]-->            mid = env->GetStaticMethodID(cls, "intMethod""(I)I");  

<!--[if !supportLists]-->34.  <!--[endif]-->            if(mid !=0)  

<!--[if !supportLists]-->35.  <!--[endif]-->            {    

<!--[if !supportLists]-->36.  <!--[endif]-->                square = env->CallStaticIntMethod(cls, mid, 5);  

<!--[if !supportLists]-->37.  <!--[endif]-->                printf("Result of intMethod: %d\n", square);  

<!--[if !supportLists]-->38.  <!--[endif]-->            }  

<!--[if !supportLists]-->39.  <!--[endif]-->  

<!--[if !supportLists]-->40.  <!--[endif]-->            mid = env->GetStaticMethodID(cls, "booleanMethod""(Z)Z")  

<!--[if !supportLists]-->41.  <!--[endif]-->            if(mid !=0)  

<!--[if !supportLists]-->42.  <!--[endif]-->            {    

<!--[if !supportLists]-->43.  <!--[endif]-->                not = env->CallStaticBooleanMethod(cls, mid, 1);  

<!--[if !supportLists]-->44.  <!--[endif]-->                printf("Result of booleanMethod: %d\n", not);  

<!--[if !supportLists]-->45.  <!--[endif]-->            }  

<!--[if !supportLists]-->46.  <!--[endif]-->        }  

<!--[if !supportLists]-->47.  <!--[endif]-->  

<!--[if !supportLists]-->48.  <!--[endif]-->            jvm->DestroyJavaVM();  

<!--[if !supportLists]-->49.  <!--[endif]-->            return 0;  

<!--[if !supportLists]-->50.  <!--[endif]-->        }  

<!--[if !supportLists]-->51.  <!--[endif]-->        else  

<!--[if !supportLists]-->52.  <!--[endif]-->            return -1;  

<!--[if !supportLists]-->53.  <!--[endif]-->    }  


<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

 C++ 實現的比較
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

C++ 代碼幾乎相同;唯一的差異在於用來訪問 JNI 函數的方法。

 C 中,爲了取出函數指針所引用的值,JNI 函數調用前要加一個(*env)-> 前綴。

 C++ 中,JNIEnv類擁有處理函數指針查找的內聯成員函數。

因此,雖然這兩行代碼訪問同一函數,但每種語言都有各自的語法,如下所示。

語法:
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

cls = (*env)->FindClass(env, "Sample2");

C++ 語法:

cls = env->FindClass("Sample2");

 

語法:
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

mid = (*env)->GetStaticMethodID(env, cls, "intMethod", "(I)I");

C++ 語法:

mid = env->GetStaticMethodID(cls, "intMethod", "(I)I");
 
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

語法:

square = env->CallStaticIntMethod(cls, mid, 5);

C++ 語法:

square = (*env)->CallStaticIntMethod(env, cls, mid, 5);


<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

語法:

(*jvm)->DestroyJavaVM(jvm);

C++ 語法:

jvm->DestroyJavaVM();

步驟 4:運行應用程序

現在準備運行這個 C 應用程序,並確保代碼正常工作。當運行 Sample2.exe 時,應該可以得到如下結果:

windows
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

使用vc6.0建一個普通的C語言工程

頭文件路徑設置同Java調用C語言裏的設置

連接時需要jvm.lib支持

這裏需要右擊建立的工程,單擊設置(Settings,link選項欄將數據庫路徑添加進來

<!--[if !vml]--><!--[endif]--> <!--[if !vml]--><!--[endif]-->

 

C:"\Program Files"\Java\jdk1.6.0_10\lib\jvm.lib

在下面的project options中加入以上語句,用空格隔開,programe Files用雙引號引起來

運行時需要jvm.dll動態庫的支持,需要在系統環境變量中增加以下路徑:

C:\Program Files\Java\jdk1.6.0_10\jre\bin\server

方法:右擊 我的電腦-》屬性-》高級-》環境變量-PATH 編輯,在原有環境變量的基礎上增加以上路徑,注意用";"號隔開

eclipose生成的java代碼放在JNI_cCalljava_test.exe同目錄下(注意按照把報名文件夾也拷過去)

E:\Sample2>JNI_cCalljava_test.exe
Result of intMethod: 25
Result of booleanMethod: 0

 

 

以上教程由凌陽教育Android培訓講師-徐哥提供,凌陽教育專注於嵌入式Linux培訓,Android培訓領域,擁有十多年的高校嵌入式師資培訓經驗,成爲中國高校嵌入式培訓第一品牌!

歡迎訪問凌陽教育官方網站:http://www.sunplusedu.com

發佈了18 篇原創文章 · 獲贊 9 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章