[英]Why do I need to reserve more than 4 bytes for a JNA pointer to receive a long when sizeof(long) is 4?
I'm using JNA to communicate with a native C library compiled with Visual Studio 2015. I'm working on a 64-bit machine. 我正在使用JNA与使用Visual Studio 2015编译的本机C库进行通信。我正在使用64位计算机。 I'm trying to receive the value of a C-function through a long pointer
long *pdays
argument. 我试图通过长指针
long *pdays
参数来接收C函数的值。 I'm getting the following exception: 我收到以下异常:
java.lang.IndexOutOfBoundsException: Bounds exceeds available space : size=4, offset=8 at com.sun.jna.Memory.boundsCheck(Memory.java:220) at com.sun.jna.Memory.getLong(Memory.java:498)
java.lang.IndexOutOfBoundsException:界限超出了可用空间:com.sun.jna.Memory.boundsCheck(Memory.java:220)的大小为com.sun.jna.Memory.boundsCheck(Memory.java:220)的offset = 8(Memory.java: 498)
I don't understand what I'm missing here, if I reserve just 4 bytes of memory for the pointer this results in the crash above, however if I reserve 8 everything goes fine. 我不明白我在这里缺少什么,如果我只为指针保留4个字节的内存,则会导致上面的崩溃,但是,如果我保留8个,一切都会很好。 However sizeof(long) returns 4, so why do I need to reserve more than 4 bytes?
但是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
It crashes because you are trying to read 8 bytes from native memory which has allocated only 4 bytes. 它崩溃是因为您试图从仅分配了4个字节的本机内存中读取8个字节。
It doesn't matter what the native type is, or that it's only 4 bytes. 原生类型是什么,还是只有4个字节都没有关系。 The
Memory
is simply holding 4 bytes that you could interpret in any fashion you wished. Memory
仅包含4个字节,您可以按照自己希望的任何方式进行解释。 You could get a byte[]
array, or an int
(with those 4 bytes) or even a short
or byte
reading only that number of bytes. 您可能会得到一个
byte[]
数组,或者一个int
(具有这4个字节),或者甚至是一个short
或byte
只能读取该数量的字节。 You could even try a String
(although without a null terminator, you'd probably read much more than the 4 bytes allowed, and who knows what you would get, so that would be dangerous.) 您甚至可以尝试使用
String
(尽管没有空终止符,但您读取的内容可能远远超过允许的4个字节,而且谁知道您会得到什么,因此很危险。)
You have asked to get a Java long
which is an 8-byte variable; 您已经要求获取一个Java
long
为8字节的变量。 accordingly, the code checks to see whether the next 8 bytes from your offset fit inside the allocated memory. 因此,代码将检查偏移量的下8个字节是否适合分配的内存。 The code from
Memory.java
has this hardcoded: 来自
Memory.java
的代码具有以下硬编码:
boundsCheck(offset, 8);
The javadoc is clear about why this is: javadoc清楚为什么会这样:
Indirect the native pointer to
malloc
space, a laPointer.getLong
.间接指向
malloc
空间的本地指针laPointer.getLong
。 But this method performs a bounds checks to ensure that the indirection does not cause memory outside themalloc
ed space to be accessed.但是此方法执行边界检查,以确保该间接操作不会导致访问已分配空间之外的
malloc
。
The correct way to do what you're doing, where you don't manually allocate the space, is to simply use a NativeLongByReference
. 在不手动分配空间的情况下,执行操作的正确方法是仅使用
NativeLongByReference
。 JNA will take care of the allocation of space and retrieval of the value on its own, and you won't have to worry about the native size. JNA会自行负责空间的分配和值的获取,您不必担心本机的大小。
NativeLongByReference pDays = new NativeLongByReference();
nativeLib.GetDaysUntilExpiration(pDays);
return pDays.getValue().longValue();
EDIT: I note in your comment you say "The C function argument is a pointer, using a NativeLongByReference would result in a "LongByReference cannot be converted to Pointer" -- this is not an issue with the C function, but with the JNA mapping in your interface. Better to change the JNA mapping of GetDaysUntilExpiration
to take a NativeLongByReference
argument. If you can't change the JNA mapping of that function, you could work around it by using pDays.getPointer()
as the argument. 编辑:我在您的注释中注意到您说“ C函数参数是一个指针,使用NativeLongByReference将导致” LongByReference无法转换为Pointer” –这不是C函数的问题,但与JNA映射有关在您的界面中,最好将
GetDaysUntilExpiration
的JNA映射更改为NativeLongByReference
参数,如果您不能更改该函数的JNA映射,则可以使用pDays.getPointer()
作为参数来解决。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.