英文:
Copy data from an unmanaged memory pointer to a managed unsigned byte array in Java
问题
Java Implementation:
public interface RSPreviewDataCallback extends Callback {
void RSPreviewDataCallback(int deviceHandle, int errorCode, Pointer imageData, int imageWidth, int imageHeight);
}
public interface RS_SDK extends StdCallLibrary {
RS_SDK INSTANCE = (RS_SDK) Native.load("RS_SDK_64", RS_SDK.class);
int RS_RegisterPreviewCallback(int deviceHandle, RSPreviewDataCallback captureCallback);
}
@Override
public void RSPreviewDataCallback(int deviceHandle, int errorCode, Pointer imageData, int imageWidth, int imageHeight) {
byte[] dataByteArray = new byte[imageWidth * imageHeight];
imageData.read(0, dataByteArray, 0, dataByteArray.length);
try {
String data = new String(dataByteArray, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
Error:
java.lang.ArrayStoreException: arraycopy: source type com.sun.jna.Pointer is not an array
Note:
- The Java code provided is your translated Java implementation of the given C# code snippet.
- The error you're encountering is due to the incorrect use of
System.arraycopywith aPointerobject. Instead, use thereadmethod on thePointerobject to copy data from native memory to a Java byte array. - The
RSPreviewDataCallbackinterface signature seems correct based on the C# delegate definition. - The updated Java code should address the memory copy issue and the error you were facing.
英文:
I have a c# code I am trying to implement in Java using JNA currently stuck in returning a preview image during my device scan process
C#
[DllImport("RS_SDK.dll",
CharSet = CharSet.Ansi,
EntryPoint = "RS_RegisterPreviewCallback")]
public static extern int RS_RegisterPreviewCallback(int deviceHandle, RSPreviewDataCallback captureCallback);
public delegate void RSRawPreviewCallback(int errorCode, byte[] imageData, int imageWidth, int imageHeight);
RSPreviewDataCallback previewCallback = new RSPreviewDataCallback(previewDataCallback);
private void previewDataCallback(int deviceHandle, int errorCode, IntPtr imageData, int imageWidth, int imageHeight)
{
log("previewDataCallback called....");
if (imageData != null)
{
int prevImageWidth = imageWidth;
int prevImageHeight = imageHeight;
byte[] prevImageData = new byte[imageWidth * imageHeight];
Marshal.Copy(imageData, prevImageData, 0, imageWidth * imageHeight);
RSRawPreviewCallback callback = new RSRawPreviewCallback(previewCallbackInt);
Invoke(callback, errorCode, prevImageData, prevImageWidth, prevImageHeight);
}
log("previewDataCallback done....");
}
m_result = RS_RegisterPreviewCallback(deviceHandle,previewCallback);
My Java implementation so far
public interface RSPreviewDataCallback extends Callback {
void RSPreviewDataCallback(int deviceHandle, int errorCode, Pointer imageData, int imageWidth, int imageHeight);
}
public interface RS_SDK extends StdCallLibrary {
RS_SDK INSTANCE = (RS_SDK)
Native.load("RS_SDK_64", RS_SDK.class);
int RS_RegisterPreviewCallback(int deviceHandle, RSPreviewDataCallback captureCallback);
}
@Override
public void RSPreviewDataCallback(int deviceHandle, int errorCode, Pointer imageData, int imageWidth, int imageHeight) {
byte[] dataByteArray = new byte[imageWidth * imageHeight];
System.arraycopy( imageData, 0, dataByteArray, 0, imageWidth * imageHeight);
try {
String data = new String(dataByteArray, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
and I run into this error:
java.lang.ArrayStoreException: arraycopy: source type com.sun.jna.Pointer is not an array
at java.base/java.lang.System.arraycopy(Native Method)
I believe the imageData is a memory reference of the byte array and Marshal.Copy(imageData, prevImageData, 0, imageWidth * imageHeight); copies the location in memory to the bitmap array.
- I am not sure if my interface
RSPreviewDataCallbacksignature is correct - I don't know if there is a JNA equivalent to copy the memory location to a byte array
答案1
得分: 1
关于问题2,从Pointer获取字节数组的JNA调用是Pointer.getByteArray()。所以你可以使用imageData.getByteArray(0, imagewidth * imageheight)从指针中获取字节。
需要注意的是,Java没有无符号的byte变量,所以虽然二进制是正确的,但你需要执行一个转换到更宽类型以获取正值。位掩码b & 0xff会将其扩展为int,并还原为“无符号”值。
关于问题1,如果你使用问题2的答案,映射将起作用。在大多数JNA函数映射中,你可以通过将byte[]数组作为参数来简化此过程。然而,JNA需要为回调具体映射的类型,所以原始数组不包括在内,因此更推荐使用Pointer方法。
英文:
Regarding question 2, the JNA call to get a byte array from a Pointer is Pointer.getByteArray(). So you could grab the bytes from the pointer using imageData.getByteArray(0, imagewidth * imageheight).
Note that Java does not have unsigned byte variables, so while the binary will be correct, you'll have to perform a conversion to a wider type to get the positive value. The bitmask b & 0xff will widen to an int for you and restore the "unsigned" value.
Regarding question 1, the mapping will work if you use the answer to question2. In most JNA function mappings of arrays, you can simplify this by putting a byte[] array as the argument. However, JNA requires specifically mapped types for callbacks, so primitive arrays aren't included, so the Pointer method is preferred.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论