繁体   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