Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 当sizeof(long)为4时,为什么我需要为JNA指针保留超过4个字节来接收long?_Java_Jna - Fatal编程技术网

Java 当sizeof(long)为4时,为什么我需要为JNA指针保留超过4个字节来接收long?

Java 当sizeof(long)为4时,为什么我需要为JNA指针保留超过4个字节来接收long?,java,jna,Java,Jna,我正在使用JNA与使用Visual Studio 2015编译的本机C库进行通信。我在一台64位机器上工作。我试图通过长指针long*pdays参数接收C函数的值。我得到以下异常: java.lang.IndexOutOfBoundsException:边界超出可用空间: com.sun.jna.Memory.boundsCheck(Memory.java:220)上的size=4,offset=8 位于com.sun.jna.Memory.getLong(Memory.java:498) 我不

我正在使用JNA与使用Visual Studio 2015编译的本机C库进行通信。我在一台64位机器上工作。我试图通过长指针
long*pdays
参数接收C函数的值。我得到以下异常:

java.lang.IndexOutOfBoundsException:边界超出可用空间: com.sun.jna.Memory.boundsCheck(Memory.java:220)上的size=4,offset=8 位于com.sun.jna.Memory.getLong(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个字节。
内存
只包含4个字节,您可以用任何方式解释它们。你可以得到一个
byte[]
数组,或者一个
int
(包含这4个字节),或者甚至一个
short
或者
byte
只读取这个字节数。您甚至可以尝试使用
字符串
(虽然没有空终止符,但您可能会读取远远超过允许的4个字节,谁知道会得到什么,因此这将是危险的。)

您要求获取一个Java
long
,它是一个8字节的变量;相应地,代码检查偏移量中的下8个字节是否适合分配的内存。
Memory.java
中的代码具有以下硬编码:

boundsCheck(offset, 8);
javadoc很清楚这是为什么:

间接指向
malloc
空间的本机指针,一个la
指针.getLong
。 但此方法执行边界检查以确保 间接寻址不会导致
malloc
ed空间之外的内存被删除 访问

在不手动分配空间的情况下,正确的做法是使用
NativeLongByReference
。JNA将自行负责空间的分配和值的检索,您不必担心本机大小

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

编辑:我注意到您在评论中说“C函数参数是指针,使用NativeLongByReference将导致”LongByReference无法转换为指针--这不是C函数的问题,而是接口中的JNA映射的问题。最好将
getdaysuntileexpiration
的JNA映射更改为采用
NativeLongByReference
参数。如果无法更改该函数的JNA映射,可以使用
pDays.getPointer()
作为参数来解决此问题

在java中,long总是8个字节。也许你想让getInt读取4字节这只是一个没有保证的想法,这是很久以前的事了,我的C技能有点生疏了,但是在x64位的机器/操作系统上(我不知道你是否使用了),C指针应该是8字节大。。。可能这就是问题的原因我不会直接使用指针和内存,但我会使用NativeLongByReference:C函数参数是指针,使用NativeLongByReference将导致“LongByReference无法转换为指针”,即不兼容的类型错误。