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.
RSPreviewDataCallback
signature is correctRegarding 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.