中文字幕精品亚洲无线码二区,国产黄a三级三级三级看三级,亚洲七七久久桃花影院,丰满少妇被猛烈进入,国产小视频在线观看网站

JNA 之(zhi) 初識(上)

      JNA(Java Native Access)框架(jia)(jia)是一個開(kai)源的(de)(de)(de)Java框架(jia)(jia),是SUN公司(si)主導(dao)開(kai)發的(de)(de)(de),建(jian)立(li)在經典(dian)的(de)(de)(de)JNI的(de)(de)(de)基礎之上(shang)(shang)的(de)(de)(de)一個框架(jia)(jia)。使用JNI調(diao)(diao)用共(gong)享類庫(.dll/.so文件)是非(fei)常麻煩(fan)的(de)(de)(de)事情,既需(xu)要編寫java代碼,又(you)要編寫C語言的(de)(de)(de)代理方法,這其中需(xu)要很多數(shu)據類型的(de)(de)(de)轉換,是讓人(ren)非(fei)常頭痛。JNA框架(jia)(jia)就是為(wei)了(le)解決這些問(wen)題(ti)和繁(fan)瑣的(de)(de)(de)事情而開(kai)發的(de)(de)(de),它提供(gong)一組(zu)Java工具類用于在運行期動態訪問(wen)系統本地共(gong)享類庫而不需(xu)要編寫任何Native/JNI代碼。開(kai)發人(ren)員只要在一個java接口(kou)中描述目標native library的(de)(de)(de)函(han)數(shu)與結構,JNA將自動實現Java接口(kou)到native function的(de)(de)(de)映(ying)射,大大降低了(le)Java調(diao)(diao)用本體共(gong)享庫的(de)(de)(de)開(kai)發難度。JNA與.NET平臺上(shang)(shang)的(de)(de)(de)P/Invoke機制一樣簡單和方便。

      你只需要下載(zai)一個(ge)jar包(bao),就可以使用(yong)JNA的(de)強大功能(neng)方便地(di)調用(yong)動態(tai)鏈接庫中(zhong)的(de)C函數。下載(zai)地(di)址是:

      JNA調用本地的庫函數

    假設有一個(ge)動態鏈接庫(ku): CnblogsJna.dll。里面有這樣(yang)一個(ge)函(han)數(shu):

void sayHello(char * name){
    printf("C Code Start...\n");
    printf("Hello! Mr %s.\n",name);
    printf("C Code End.\n");
}

  ;    此函數接收一個代表姓名的字(zi)符(fu)指針,然后在控制臺上輸出幾句字(zi)符(fu)串。

      為了調用這(zhe)個(ge)函(han)數,使用JNA,我們需要編寫下面的JAVA代碼:

      1、接口ICnblogsJna.java

import com.sun.jna.Library;
import com.sun.jna.Native;

/**
 * @author BCH)王國成
 */
public interface ICnblogsJna extends Library {
    // 接(jie)口實例
    ICnblogsJna INSTANCE = (ICnblogsJna) Native.loadLibrary("CnblogsJna",ICnblogsJna.class);

    // 與(yu)C代碼(ma)映(ying)射的函數
    public void sayHello(String name);
}

      注意:接口(kou)需要繼承制(zhi)JNA的Library接口(kou);

             接口內部需要一個公共靜態常量INSTANCE, 通過這個常量,就可以獲得這個接口的實例,從而使用接口的方法。也就是調用動態鏈接庫CnblogsJna.dll中的sayHello函數了。
            如果使用JNI,你需要使用System.loadLibrary方法,來加載我們專為JNI編寫的動態鏈接庫,這個動態鏈接庫實際上是我們真正需要的動態鏈接庫的代理。使用JNA是,需要用JNA類庫的Native類的loadLibrary函數,是直接把我們需要的動態鏈接庫載入進來。使用JNA,我們不需要編寫作為代理的動態鏈接庫,不需要編寫一行原生代碼。
            Native類(lei)的(de)loadLibrary方(fang)法有兩個參數(shu)(shu):第(di)一個參數(shu)(shu)是.dll或者.so文(wen)件(jian)的(de)名(ming)字,但不帶(dai)后綴名(ming)。這符合JNI的(de)規范(fan),因為(wei)帶(dai)了(le)后綴名(ming)就不可以跨操作(zuo)系統(tong)平臺了(le)。第(di)二(er)個參數(shu)(shu)是本(ben)接口(kou)的(de)Class類(lei)型,JNA通過(guo)這個Class類(lei)型,根據指定的(de)dll/.so文(wen)件(jian),動態創建接口(kou)的(de)實(shi)例。

      2、調(diao)用動(dong)態鏈接庫文件中函數的Java方(fang)法():

/**
 * @author BCH)王國成(cheng)
 */
public class CnblogsJna {
    /**
     * 入口函數
     * @param args
     */
    public static void main(String[] args) {
        // 調用動態鏈庫中的sayHello函數
        ICnblogsJna.INSTANCE.sayHello("Wanggc/王國成");
    }
}

      方法(fa)很簡單,就像調用(yong)Java自己的(de)函數一(yi)樣。執行輸出(chu)結果如下:

     

      和原生代碼的類型映射

      跨平臺(tai),跨語(yu)言(yan)調用(yong)的(de)(de)難點,就是(shi)不(bu)(bu)同語(yu)言(yan)之間數據(ju)類(lei)型不(bu)(bu)一(yi)致造成的(de)(de),JNA也(ye)不(bu)(bu)例(li)外(wai),要想跨平臺(tai)調用(yong),數據(ju)類(lei)型轉換是(shi)個(ge)無法回避的(de)(de)問題。JNA提供了Java和(he)原生代碼的(de)(de)類(lei)型映射。

      Java和C數據(ju)類型的對應(ying)表如下:

Java

C

原生表

 boolean

 int

 32位整(zheng)數 (可(ke)定(ding)制(zhi))

 byte

 char 

 8位整數

 char

 wchar_t

 平臺依賴

 short

 short

 16位整數

 int

 int

 32位(wei)整數

 long

long long, __int64

 64位整(zheng)數

 float

 float

 32位浮點(dian)數(shu)

 double

 double

 64位浮點(dian)數(shu)

 Buffer/Pointer

 pointer

 平臺(tai)依賴(lai)(32或 64位指針)

 <T>[] (基本類型的數組)

 pointer/array

32或 64位指(zhi)針(zhen)(參(can)數(shu)/返(fan)回值)

鄰接內存(cun)(結構(gou)體(ti)成員)

 String

 char*

/0結束的數組 (native encoding or jna.encoding)

 WString

 wchar_t*

 /0結束的數組(unicode)

 String[]

 char**

 /0結束的(de)數(shu)(shu)組的(de)數(shu)(shu)組

 WString[]

 wchar_t**

 /0結束的寬字(zi)符(fu)數(shu)組(zu)的數(shu)組(zu)

 Structure

 struct*/struct

指(zhi)向結構體(ti)(ti)的(de)指(zhi)針 (參數或返回值) (或者明確指(zhi)定是結構體(ti)(ti)指(zhi)針)
結(jie)構(gou)體(ti)(結(jie)構(gou)體(ti)的成員(yuan)) (或者明確(que)指定是結(jie)構(gou)體(ti))

 Union

union 

 等同于結構體(ti)

 Structure[]

 struct[]

 結構體的數(shu)組,鄰(lin)接(jie)內存

 Callback

 <T> (*fp)()

 Java函數指針(zhen)或原(yuan)生函數指針(zhen)

 NativeMapped

 varies

 依(yi)賴于定義

 NativeLong

 long

 平臺依賴(lai)(32或64位整(zheng)數)

 PointerType

 pointer

 和 Pointer相同(tong)

 

  &nbsp;   由(you)于跨平(ping)臺(tai)和跨語言尤其(qi)自身無法(fa)克服的(de)確定(ding),所以盡量少跨平(ping)臺(tai)、跨語言傳(chuan)遞數(shu)(shu)據(ju)(ju)(ju)。如(ru)果(guo)必(bi)須(xu)這樣做,也盡量使用簡單的(de)數(shu)(shu)據(ju)(ju)(ju)類(lei)型(xing)。如(ru)果(guo)有復雜的(de)數(shu)(shu)據(ju)(ju)(ju)類(lei)型(xing)需要在(zai)(zai)Java和原生(sheng)函(han)數(shu)(shu)中傳(chuan)遞,那么我們就必(bi)須(xu)在(zai)(zai)Java中模(mo)擬這種復雜的(de)原生(sheng)類(lei)型(xing)。這將大(da)(da)大(da)(da)增加實(shi)現的(de)難度,甚(shen)至無法(fa)實(shi)現。如(ru)果(guo)在(zai)(zai)Java和原生(sheng)函(han)數(shu)(shu)間(jian)存(cun)在(zai)(zai)大(da)(da)量的(de)數(shu)(shu)據(ju)(ju)(ju)傳(chuan)遞,一方(fang)面,會(hui)損失程序的(de)性能;另一方(fang)面會(hui)造成內存(cun)碎片(pian),Java調(diao)用原生(sheng)函(han)數(shu)(shu)時,會(hui)把數(shu)(shu)據(ju)(ju)(ju)固定(ding)在(zai)(zai)內存(cun)中,這樣原生(sheng)函(han)數(shu)(shu)才可以訪問這些(xie)Java數(shu)(shu)據(ju)(ju)(ju)。這些(xie)數(shu)(shu)據(ju)(ju)(ju),JVM的(de)GC不能管理,就會(hui)造成內存(cun)碎片(pian)。

posted @ 2012-06-29 10:09  孤旅者  閱讀(11853)  評論(0)    收藏  舉報