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

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个字节),或者甚至是一个shortbyte只能读取该数量的字节。 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 la Pointer.getLong . 间接指向malloc空间的本地指针la Pointer.getLong But this method performs a bounds checks to ensure that the indirection does not cause memory outside the malloc 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.

相关问题 为什么用 AES 加密 16 个字节时,密文长度为 32 个字节? - Why is the ciphertext 32 bytes long when encrypting 16 bytes with AES? 在JNA的Pointer.getPointerArray(长基数)和Pointer.getStringArray(长基数)中,“基数”是什么意思? - What does 'base' mean in JNA's Pointer.getPointerArray(long base) and Pointer.getStringArray(long base)? 为什么在使用Long而不是Integer时得到ClassCastException? - Why do I get a ClassCastException when using Long instead of Integer? 如何使用SecureRandom()。nextBytes将字节写到文件中? - How do I write bytes to a file based on a long with SecureRandom().nextBytes? 如何手动将字节分配给 Kotlin 中的 long? - How do I manually assign bytes to a long in Kotlin? Pointer(long)在com.sun.jna.Pointer中不是公共的; 无法从外部包访问 - Pointer(long) is not public in com.sun.jna.Pointer; Cannot be accessed from outside package android中保存的位图读取时长度为3个字节 - Saved bitmap in android is 3 bytes long when read 将 long 移位超过 31 位(java) - Shifting a long by more than 31 bits (java) Java将long转换为字节 - 哪种方法更有效 - Java Converting long to bytes - which approach is more efficient 如何将指针映射到JNA中的结构数组 - How do I map a pointer to an array of structures in JNA
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM