最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java高級用法之JNA中的Structure

 更新時(shí)間:2022年04月18日 16:09:50   作者:程序那些事  
這篇文章主要介紹了java高級用法之JNA中的Structure,JNA提供了Structure類,來幫助我們進(jìn)行這些映射處理,下面文章詳細(xì)的介紹過程需要的小伙伴可以參考一下

簡介

前面我們講到了JNA中JAVA代碼和native代碼的映射,雖然可以通過TypeMapper來將JAVA中的類型和native中的類型進(jìn)行映射,但是native中的數(shù)據(jù)類型都是基礎(chǔ)類型,如果native中的數(shù)據(jù)類型是復(fù)雜的struct類型該如何進(jìn)行映射呢?

不用怕,JNA提供了Structure類,來幫助我們進(jìn)行這些映射處理。

native中的struct

什么時(shí)候會用到struct呢?一般情況下,當(dāng)我們需要自定義一個(gè)數(shù)據(jù)類的時(shí)候,一般情況下,在JAVA中需要定義一個(gè)class(在JDK17中,可以使用更加簡單的record來進(jìn)行替換),但是為一個(gè)數(shù)據(jù)結(jié)構(gòu)定義class顯然有些臃腫,所以在native語言中,有一些更簡單的數(shù)據(jù)結(jié)構(gòu)叫做struct。

我們先看一個(gè)struct的定義:

typedef struct _Point {
  int x, y;
} Point;

上面的代碼中,我們定義了一個(gè)Pointer的struct數(shù)據(jù)類下,在其中定義了int的x和y值表示Point的橫縱坐標(biāo)。

struct的使用有兩種情況,一種是值傳遞,一種是引用傳遞。先來看下這兩種情況在native方法中是怎么使用的:

引用傳遞:

Point* translate(Point* pt, int dx, int dy);

值傳遞:

Point translate(Point pt, int dx, int dy);

Structure

那么對于native方法中的struct數(shù)據(jù)類型的使用方式,應(yīng)該如何進(jìn)行映射呢? JNA為我們提供了Structure類。

默認(rèn)情況下如果Structure是作為參數(shù)或者返回值,那么映射的是struct*,如果表示的是Structure中的一個(gè)字段,那么映射的是struct。

當(dāng)然你也可以強(qiáng)制使用Structure.ByReference 或者 Structure.ByValue 來表示是傳遞引用還是傳值。

我們看下上面的native的例子中,如果使用JNA的Structure來進(jìn)行映射應(yīng)該怎么實(shí)現(xiàn):

指針映射:

class Point extends Structure { public int x, y; }
Point translate(Point pt, int x, int y);
...
Point pt = new Point();
Point result = translate(pt, 100, 100);

傳值映射:

class Point extends Structure {
    public static class ByValue extends Point implements Structure.ByValue { }
    public int x, y;
}
Point.ByValue translate(Point.ByValue pt, int x, int y);
...
Point.ByValue pt = new Point.ByValue();
Point result = translate(pt, 100, 100);

Structure內(nèi)部提供了兩個(gè)interface,分別是ByValue和ByReference:

public abstract class Structure {

    public interface ByValue { }

    public interface ByReference { }

要使用的話,需要繼承對應(yīng)的interface。

特殊類型的Structure

除了上面我們提到的傳值或者傳引用的struct,還有其他更加復(fù)雜的struct用法。

結(jié)構(gòu)體數(shù)組作為參數(shù)

首先來看一下結(jié)構(gòu)體數(shù)組作為參數(shù)的情況:

void get_devices(struct Device[], int size);

對應(yīng)結(jié)構(gòu)體數(shù)組,可以直接使用JNA中對應(yīng)的Structure數(shù)組來進(jìn)行映射:

int size = ...
Device[] devices = new Device[size];
lib.get_devices(devices, devices.length);

結(jié)構(gòu)體數(shù)組作為返回值

如果native方法返回的是一個(gè)指向結(jié)構(gòu)體的指針,其本質(zhì)上是一個(gè)結(jié)構(gòu)體數(shù)組,我們應(yīng)該怎么處理呢?

先看一下native方法的定義:

struct Display* get_displays(int* pcount);
void free_displays(struct Display* displays);

get_displays方法返回的是一個(gè)指向結(jié)構(gòu)體數(shù)組的指針,pcount是結(jié)構(gòu)體的個(gè)數(shù)。

對應(yīng)的JAVA代碼如下:

Display get_displays(IntByReference pcount);
void free_displays(Display[] displays);

對于第一個(gè)方法來說,我們只返回了一個(gè)Display,但是可以通過Structure.toArray(int) 方法將其轉(zhuǎn)換成為結(jié)構(gòu)體數(shù)組。傳入到第二個(gè)方法中,具體的調(diào)用方式如下:

IntByReference pcount = new IntByReference();
Display d = lib.get_displays(pcount);
Display[] displays = (Display[])d.toArray(pcount.getValue());
...
lib.free_displays(displays);

結(jié)構(gòu)體中的結(jié)構(gòu)體

結(jié)構(gòu)體中也可以嵌入結(jié)構(gòu)體,先看下native方法的定義:

typedef struct _Point {
  int x, y;
} Point;

typedef struct _Line {
  Point start;
  Point end;
} Line;

對應(yīng)的JAVA代碼如下:

class Point extends Structure {
  public int x, y;
}

class Line extends Structure {
  public Point start;
  public Point end;
}

如果是下面的結(jié)構(gòu)體中的指向結(jié)構(gòu)體的指針:

typedef struct _Line2 {
  Point* p1;
  Point* p2;
} Line2;

那么對應(yīng)的代碼如下:

class Point extends Structure {
    public static class ByReference extends Point implements Structure.ByReference { }
    public int x, y;
}
class Line2 extends Structure {
  public Point.ByReference p1;
  public Point.ByReference p2;
}

或者直接使用Pointer作為Structure的屬性值:

class Line2 extends Structure {
  public Pointer p1;
  public Pointer p2;
}

Line2 line2;
Point p1, p2;
...
line2.p1 = p1.getPointer();
line2.p2 = p2.getPointer();

結(jié)構(gòu)體中的數(shù)組

如果結(jié)構(gòu)體中帶有固定大小的數(shù)組:

typedef struct _Buffer {
  char buf1[32];
  char buf2[1024];
} Buffer;

那么我們在JAVA中需要指定數(shù)據(jù)的大?。?/strong>

class Buffer extends Structure {
  public byte[] buf1 = new byte[32];
  public byte[] buf2 = new byte[1024];
}

如果結(jié)構(gòu)體中是動態(tài)大小的數(shù)組:

typedef struct _Header {
  int flags;
  int buf_length;
  char buffer[1];
} Header;

那么我們需要在JAVA的結(jié)構(gòu)體中定義一個(gè)構(gòu)造函數(shù),傳入bufferSize的大小,并分配對應(yīng)的內(nèi)存空間:

結(jié)構(gòu)體中的可變字段

默認(rèn)情況下結(jié)構(gòu)體中的內(nèi)容和native memory的內(nèi)容是一致的。JNA會在函數(shù)調(diào)用之前將Structure的內(nèi)容寫入到native memory中,并且在函數(shù)調(diào)用之后,將 native memory中的內(nèi)容回寫到Structure中。

默認(rèn)情況下是將結(jié)構(gòu)體中的所有字段都進(jìn)行寫入和寫出。但是在某些情況下,我們希望某些字段不進(jìn)行自動更新。這個(gè)時(shí)候就可以使用volatile關(guān)鍵字,如下所示:

class Data extends com.sun.jna.Structure {
  public volatile int refCount;
  public int value;
}
...
Data data = new Data();

當(dāng)然,你也可以強(qiáng)制使用Structure.writeField(String)來將字段信息寫入內(nèi)存中,或者使用Structure.read() 來更新整個(gè)結(jié)構(gòu)體的信息或者使用data.readField(“refCount”)來更新具體字段信息。

結(jié)構(gòu)體中的只讀字段

如果不想從JAVA代碼中對Structure的內(nèi)容進(jìn)行修改,則可以將對應(yīng)的字段標(biāo)記為final。在這種情況下,雖然JAVA代碼不能直接對其進(jìn)行修改,但是仍然可以調(diào)用read方法從native memory中讀取對應(yīng)的內(nèi)容并覆蓋Structure中對應(yīng)的值。

來看下JAVA中如何使用final字段:

class ReadOnly extends com.sun.jna.Structure {
  public final int refCount;
  {
    // 初始化
    refCount = -1;
    // 從內(nèi)存中讀取數(shù)據(jù)
    read();
  }
}

注意所有的字段的初始化都應(yīng)該在構(gòu)造函數(shù)或者靜態(tài)方法塊中進(jìn)行。

總結(jié)

結(jié)構(gòu)體是native方法中經(jīng)常會使用到的一種數(shù)據(jù)類型,JNA中對其進(jìn)行映射的方法是我們要掌握的。

到此這篇關(guān)于java高級用法之JNA中的Structure的文章就介紹到這了,更多相關(guān)java 中的Structure內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot整合Servlet和Filter和Listener組件詳解

    SpringBoot整合Servlet和Filter和Listener組件詳解

    這篇文章主要介紹了SpringBoot整合Servlet和Filter和Listener組件詳解,在整合某報(bào)表插件時(shí)就需要使用Servlet,Spring Boot中對于整合這些基本的Web組件也提供了很好的支持,需要的朋友可以參考下
    2024-01-01
  • java中的Reference和引用類型實(shí)例精講

    java中的Reference和引用類型實(shí)例精講

    這篇文章主要為大家介紹了java中的Reference和引用類型示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-09-09
  • @AutoConfigurationPackage與@ComponentScan注解區(qū)別

    @AutoConfigurationPackage與@ComponentScan注解區(qū)別

    這篇文章主要介紹了@AutoConfigurationPackage與@ComponentScan注解區(qū)別,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • java使用poi讀取excel內(nèi)容方法實(shí)例

    java使用poi讀取excel內(nèi)容方法實(shí)例

    本文介紹java使用poi讀取excel內(nèi)容的實(shí)例,大家參考使用吧
    2014-01-01
  • java實(shí)現(xiàn)文件上傳功能

    java實(shí)現(xiàn)文件上傳功能

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)文件上傳功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-12-12
  • SpringBoot自動裝配原理小結(jié)

    SpringBoot自動裝配原理小結(jié)

    Spring Boot主要作用就是簡化Spring應(yīng)用的開發(fā),開發(fā)者只需要通過少量代碼就可以創(chuàng)建一個(gè)Spring應(yīng)用,而達(dá)到這一目的最核心的思想就是約定優(yōu)于配置。
    2021-05-05
  • java中對list分頁并顯示數(shù)據(jù)到頁面實(shí)例代碼

    java中對list分頁并顯示數(shù)據(jù)到頁面實(shí)例代碼

    這篇文章主要介紹了java中對list分頁并顯示數(shù)據(jù)到頁面實(shí)例代碼,分享了相關(guān)代碼示例,小編覺得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2018-02-02
  • java計(jì)算值所占的百分比,結(jié)果為100%問題

    java計(jì)算值所占的百分比,結(jié)果為100%問題

    這篇文章主要介紹了java計(jì)算值所占的百分比,結(jié)果為100%問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • Java反射之深入理解

    Java反射之深入理解

    這篇文章主要介紹了Java反射機(jī)制的深入理解,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-09-09
  • SpringBoot整合Prometheus如何實(shí)現(xiàn)資源監(jiān)控

    SpringBoot整合Prometheus如何實(shí)現(xiàn)資源監(jiān)控

    本文介紹了如何使用Prometheus監(jiān)控SpringBoot應(yīng)用,Prometheus是一個(gè)開源的監(jiān)控和告警工具,SpringBootActuator提供了監(jiān)控和管理SpringBoot應(yīng)用的工具,通過添加依賴、配置Actuator和Prometheus,可以實(shí)現(xiàn)對SpringBoot應(yīng)用的實(shí)時(shí)監(jiān)控
    2024-12-12

最新評論

阜康市| 辽宁省| 隆尧县| 山东省| 赤城县| 东港市| 林口县| 元朗区| 乌兰县| 奎屯市| 连州市| 平武县| 耒阳市| 克什克腾旗| 昭通市| 宁明县| 南昌市| 灵武市| 砀山县| 托克托县| 大安市| 古浪县| 双牌县| 高尔夫| 肃南| 贡嘎县| 上高县| 陵川县| 宜阳县| 五寨县| 安宁市| 成安县| 西乌珠穆沁旗| 隆德县| 文安县| 惠安县| 犍为县| 阜城县| 开原市| 巴中市| 贡嘎县|