英文:
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.arraycopy
with aPointer
object. Instead, use theread
method on thePointer
object to copy data from native memory to a Java byte array. - The
RSPreviewDataCallback
interface 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
RSPreviewDataCallback
signature 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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论