JNI技術基礎(2)——從零開始編寫JNI代碼

來源:互聯網
上載者:User

標籤:android   style   blog   http   color   io   os   使用   java   

 

書接上文: 《JNI技術基礎(1)——從零開始編寫JNI代碼》

 

2.編譯來源程式HelloWorld.java並產生HelloWorld.class

 

3.產生標頭檔HelloWorld.h

     在Linux控制台輸入命令:javah –jni HelloWorld 產生HelloWorld.h標頭檔

//HelloWorld.h/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class HelloWorld */#ifndef _Included_HelloWorld#define _Included_HelloWorld#ifdef __cplusplusextern "C" {#endif/* * Class:     HelloWorld * Method:    print * Signature: ()V */JNIEXPORT void JNICALL Java_HelloWorld_print  (JNIEnv *, jobject);#ifdef __cplusplus}#endif#endif

       這個標頭檔中便告訴了我們需要用C/C++實現的函數的原型,即

              JNIEXPORT void JNICALL Java_HelloWorld_print ( JNIEnv * env, jobject obj)

       我們只需要按照這種格式完成其函數體的實現即可,函數名的格式:

              Java_類名_函數名

       參數env代表java虛擬機器環境,Java傳過來的參數和c有很大的不同,需要調用JVM提供的介面來轉換成C類型的,就是通過調用env方法來完成轉換的。
       參數obj代表調用的對象,相當於c++的this。當c函數需要改變調用對象成員變數時,可以通過操作這個對象來完成。


4.實現C/C++函數

       這塊兒有點偷懶,並沒有逐個字母去敲,而是通過拷貝標頭檔的方法,然後刪除標頭檔中的無用資訊,填充函數體的方法來建立HelloWorld.c檔案,主要是因為JNI函數名都比較複雜,害怕疏忽敲錯某個字元,或者少實現了某個函數,見諒。

//HelloWorld.c#include <jni.h>#include <stdio.h>#include "HelloWorld.h"/* * Class:     HelloWorld * Method:    print * Signature: ()V */JNIEXPORT void JNICALL Java_HelloWorld_print (JNIEnv *, jobject){    printf("Hello World!\n");}

由上面可以看出,函數體的實現和普通的C/C++函數完全相同,不同的只是函數原型的格式。
需要注意的一點就是記得添加2個標頭檔:jni.h和HelloWorld.h 。

 

5.編譯產生庫檔案

        gcc  -I/usr/lib/jvm/java-1.5.0-sun-1.5.0.22/include/linux/
                -I/usr/lib/jvm/java-1.5.0-sun-1.5.0.22/include/
                -fPIC  -shared  -o libHelloWorld.so  HelloWorld.c
       在編譯的時候需要注意的就是記得加上java的兩個路徑,該路徑根據你的java環境的實際安裝路徑而設定,其餘的和編譯普通的動態庫方法相同。

第一個紅色方框中圈出了我們經常範的一個錯誤,就是沒有填寫JNI函數的兩個形參,雖然我們這裡用不到它們,但是也必須寫上,否則無法通過編譯。

//HelloWorld.c#include <jni.h>#include <stdio.h>#include "HelloWorld.h"/* * Class:     HelloWorld * Method:    print * Signature: ()V */JNIEXPORT void JNICALL Java_HelloWorld_print (JNIEnv *env, jobject obj){    printf("Hello World!\n");}

  

6.運行Java程式

方框圈出了兩個經常範的錯誤,第一個錯誤產生的原因是找不到剛剛產生的C/C++動態庫,需要手動指定庫的路徑,當然也可以把該庫拷貝到系統庫檔案目錄中。

手動指定動態庫路徑的方法是使用參數 -Djava.library.path

        java –Djava.library.path = "."  HelloWorld

第二個錯誤產生的原因是使用參數時,"="的前面或者後面使用了空格,去掉等號前後的空格即可。

 

OK,大功告成,終於看到久違的HelloWorld!

 

7.附錄:一個簡單的常式

<1>. MyTools.java

//MyTools.javaclass MyTools{    private native int myAdd(int x, int y);    private native int mySub(int x, int y);    public static void main(String[] args){        int a = 5;        int b = 7;        int c = new MyTools().myAdd(a, b);        int d = new MyTools().mySub(a, b);        System.out.println(a + " + " + b + " = " + c);        System.out.println(a + " - " + b + " = " + d);    }    static{        System.loadLibrary("MyTools");    }}

  

<2>. 自動產生MyTools.h標頭檔

//MyTools.h/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class MyTools */#ifndef _Included_MyTools#define _Included_MyTools#ifdef __cplusplusextern "C" {#endif/* * Class:     MyTools * Method:    myAdd * Signature: (II)I */JNIEXPORT jint JNICALL Java_MyTools_myAdd  (JNIEnv *, jobject, jint, jint);/* * Class:     MyTools * Method:    mySub * Signature: (II)I */JNIEXPORT jint JNICALL Java_MyTools_mySub  (JNIEnv *, jobject, jint, jint);#ifdef __cplusplus}#endif#endif

  

<3>. 函數體的C/C++實現myTools.c

//MyTools.c#include <jni.h>#include "MyTools.h"/* * Class:     MyTools * Method:    myAdd * Signature: (II)I */JNIEXPORT jint JNICALL Java_MyTools_myAdd (JNIEnv *env, jobject obj, jint x, jint y){    return (x + y);}/* * Class:     MyTools * Method:    mySub * Signature: (II)I */JNIEXPORT jint JNICALL Java_MyTools_mySub (JNIEnv *env, jobject obj, jint x, jint y){    return (x - y);}

運行結果:

 

說明:

     1.大多數情況下,JNI都是在Android開發中使用,本文的目的是使用最簡單的語言描述出JNI最基本、最簡單的使用流程,所以並沒有使用Android架構,Android架構中的一大堆東西會阻擋我們的視線,無法專註於對JNI本身的瞭解,而Android下JNI的使用流程和Java是基本相同的,後面會有專門的篇幅介紹Android下JNI編程。
     2.此處實現了使用JNI傳遞簡單的參數x和y。

     3.通過上面兩個例子,相信大家已經可以寫出自己的簡單的 JNI 應用,但是整個 JNI 系統相當複雜,尤其是參數和傳回值的傳遞方面,後面會有專門篇幅詳細介紹。

 

< end >

 

 

JNI技術基礎(2)——從零開始編寫JNI代碼

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.