欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java高級用法之JNA中的Structure

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

簡介

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

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

native中的struct

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

我們先看一個struct的定義:

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

上面的代碼中,我們定義了一個Pointer的struct數據類下,在其中定義了int的x和y值表示Point的橫縱坐標。

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

引用傳遞:

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

值傳遞:

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

Structure

那么對于native方法中的struct數據類型的使用方式,應該如何進行映射呢? JNA為我們提供了Structure類。

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

當然你也可以強制使用Structure.ByReference 或者 Structure.ByValue 來表示是傳遞引用還是傳值。

我們看下上面的native的例子中,如果使用JNA的Structure來進行映射應該怎么實現:

指針映射:

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內部提供了兩個interface,分別是ByValue和ByReference:

public abstract class Structure {

    public interface ByValue { }

    public interface ByReference { }

要使用的話,需要繼承對應的interface。

特殊類型的Structure

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

結構體數組作為參數

首先來看一下結構體數組作為參數的情況:

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

對應結構體數組,可以直接使用JNA中對應的Structure數組來進行映射:

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

結構體數組作為返回值

如果native方法返回的是一個指向結構體的指針,其本質上是一個結構體數組,我們應該怎么處理呢?

先看一下native方法的定義:

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

get_displays方法返回的是一個指向結構體數組的指針,pcount是結構體的個數。

對應的JAVA代碼如下:

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

對于第一個方法來說,我們只返回了一個Display,但是可以通過Structure.toArray(int) 方法將其轉換成為結構體數組。傳入到第二個方法中,具體的調用方式如下:

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

結構體中的結構體

結構體中也可以嵌入結構體,先看下native方法的定義:

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

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

對應的JAVA代碼如下:

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

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

如果是下面的結構體中的指向結構體的指針:

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

那么對應的代碼如下:

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();

結構體中的數組

如果結構體中帶有固定大小的數組:

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

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

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

如果結構體中是動態(tài)大小的數組:

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

那么我們需要在JAVA的結構體中定義一個構造函數,傳入bufferSize的大小,并分配對應的內存空間:

結構體中的可變字段

默認情況下結構體中的內容和native memory的內容是一致的。JNA會在函數調用之前將Structure的內容寫入到native memory中,并且在函數調用之后,將 native memory中的內容回寫到Structure中。

默認情況下是將結構體中的所有字段都進行寫入和寫出。但是在某些情況下,我們希望某些字段不進行自動更新。這個時候就可以使用volatile關鍵字,如下所示:

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

當然,你也可以強制使用Structure.writeField(String)來將字段信息寫入內存中,或者使用Structure.read() 來更新整個結構體的信息或者使用data.readField(“refCount”)來更新具體字段信息。

結構體中的只讀字段

如果不想從JAVA代碼中對Structure的內容進行修改,則可以將對應的字段標記為final。在這種情況下,雖然JAVA代碼不能直接對其進行修改,但是仍然可以調用read方法從native memory中讀取對應的內容并覆蓋Structure中對應的值。

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

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

注意所有的字段的初始化都應該在構造函數或者靜態(tài)方法塊中進行。

總結

結構體是native方法中經常會使用到的一種數據類型,JNA中對其進行映射的方法是我們要掌握的。

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

相關文章

  • Java使用hutool實現文件大小的友好輸出

    Java使用hutool實現文件大小的友好輸出

    這篇文章主要為大家詳細介紹了Java如何使用hutool實現文件大小的友好輸出,文中的示例代碼講解詳細,具有一定的學習價值,感興趣的小伙伴可以了解下
    2023-11-11
  • 詳細了解MyBatis的異常處理機制

    詳細了解MyBatis的異常處理機制

    本文將對MyBatis的異常體系以及異常使用進行學習,MyBatis版本是3.5.6,作為一款成熟的ORM框架,MyBatis有自己一套成熟的異常處理體系,,需要的朋友可以參考下
    2023-06-06
  • 解決@RequestMapping和@FeignClient放在同一個接口上遇到的坑

    解決@RequestMapping和@FeignClient放在同一個接口上遇到的坑

    這篇文章主要介紹了解決@RequestMapping和@FeignClient放在同一個接口上遇到的坑,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • 詳解JAVA的控制語句

    詳解JAVA的控制語句

    這篇文章主要介紹了Java中的控制語句,循環(huán)等語句是Java編程中流程控制的基礎,需要的朋友可以參考下,希望能夠給你帶來幫助
    2021-11-11
  • 詳解Java synchronized關鍵字的用法

    詳解Java synchronized關鍵字的用法

    在多線程編程中常常使用鎖機制來確保同一時刻只有一個線程能夠修改共享內存,在Java中一般是使用synchronized作為鎖機制,下面就讓我們來學習一下如何使用synchronized實現線程安全吧
    2023-08-08
  • java中的數組初始化賦初值方式

    java中的數組初始化賦初值方式

    這篇文章主要介紹了java中的數組初始化賦初值方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-05-05
  • Java類加載之Class對象到Klass模型詳解

    Java類加載之Class對象到Klass模型詳解

    這篇文章主要介紹了Java類加載之Class對象到Klass模型詳解,每一個Java類在JVM中都會對應創(chuàng)建一個C++類實例,我們稱這個C++類為Klass實例,Klass實例里面存儲了java類中所描述的方法、字段、屬性等,需要的朋友可以參考下
    2023-08-08
  • java 中cookie的詳解及簡單實例

    java 中cookie的詳解及簡單實例

    這篇文章主要介紹了java 中cookie的詳解及簡單實例的相關資料,這里對cookie 的建立與讀取,和設定cookie 生命周期等詳細介紹,需要的朋友可以參考下
    2017-01-01
  • Java中的8大基本數據類型詳解

    Java中的8大基本數據類型詳解

    這篇文章主要介紹了Java中8大基本數據類型的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-12-12
  • Struts2之Validator驗證框架的詳細介紹

    Struts2之Validator驗證框架的詳細介紹

    Struts2中提供了數據校驗驗證數據例如驗證郵件、數字等,本篇文章介紹了Struts2之Validator的詳細介紹,有興趣的可以了解一下。
    2017-03-03

最新評論