簡體   English   中英

當sizeof(long)為4時,為什么需要為JNA指針保留4個以上的字節才能接收long?

[英]Why do I need to reserve more than 4 bytes for a JNA pointer to receive a long when sizeof(long) is 4?

我正在使用JNA與使用Visual Studio 2015編譯的本機C庫進行通信。我正在使用64位計算機。 我試圖通過長指針long *pdays參數來接收C函數的值。 我收到以下異常:

java.lang.IndexOutOfBoundsException:界限超出了可用空間:com.sun.jna.Memory.boundsCheck(Memory.java:220)的大小為com.sun.jna.Memory.boundsCheck(Memory.java:220)的offset = 8(Memory.java: 498)

我不明白我在這里缺少什么,如果我只為指針保留4個字節的內存,則會導致上面的崩潰,但是,如果我保留8個,一切都會很好。 但是sizeof(long)返回4,那么為什么我需要保留4個以上的字節?

    System.out.println(NativeLong.SIZE); // --> 4
    System.out.println(Native.LONG_SIZE); // --> 4

    // Pointer pDays = new Memory(Native.LONG_SIZE); Results in IndexOutOfBoundsException
    Pointer pDays = new Memory(8); // 

    nativeLib.GetDaysUntilExpiration(pDays);
    return pDays.getLong(0); // crashes here when reserving just 4 bytes

它崩潰是因為您試圖從僅分配了4個字節的本機內存中讀取8個字節。

原生類型是什么,還是只有4個字節都沒有關系。 Memory僅包含4個字節,您可以按照自己希望的任何方式進行解釋。 您可能會得到一個byte[]數組,或者一個int (具有這4個字節),或者甚至是一個shortbyte只能讀取該數量的字節。 您甚至可以嘗試使用String (盡管沒有空終止符,但您讀取的內容可能遠遠超過允許的4個字節,而且誰知道您會得到什么,因此很危險。)

您已經要求獲取一個Java long為8字節的變量。 因此,代碼將檢查偏移量的下8個字節是否適合分配的內存。 來自Memory.java的代碼具有以下硬編碼:

boundsCheck(offset, 8);

javadoc清楚為什么會這樣:

間接指向malloc空間的本地指針la Pointer.getLong 但是此方法執行邊界檢查,以確保該間接操作不會導致訪問已分配空間之外的malloc

在不手動分配空間的情況下,執行操作的正確方法是僅使用NativeLongByReference JNA會自行負責空間的分配和值的獲取,您不必擔心本機的大小。

NativeLongByReference pDays = new NativeLongByReference();
nativeLib.GetDaysUntilExpiration(pDays);
return pDays.getValue().longValue(); 

編輯:我在您的注釋中注意到您說“ C函數參數是一個指針,使用NativeLongByReference將導致” LongByReference無法轉換為Pointer” –這不是C函數的問題,但與JNA映射有關在您的界面中,最好將GetDaysUntilExpiration的JNA映射更改為NativeLongByReference參數,如果您不能更改該函數的JNA映射,則可以使用pDays.getPointer()作為參數來解決。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM