I have a C++ method with the following signature:
int cppGetData(string& data);
It should be called from a Java method.
Version I :
byte[] javaGetData();
Which should return null
if cppGetData
returns a non zero return code.
I understand that I have to write something like this:
JNIEXPORT jbyteArray JNICALL jniGetData(JNIEnv * env, jobject thisObj)
(
string data;
if (cppGetData(data))
{
return NULL;
}
jbyteArray jData = env->NewByteArray(data.size());
env->SetByteArrayRegion(jData, 0, data.size(), (jbyte *)data.c_str());
return jData;
}
My problem is that I loose the status returned by cppGetData
. On the other hand, Java does not have return by reference, so I am puzzled. How do I return byte[]
and an integer status?
Of course, I could have a wrapper, something like this:
public class ByteArrayWrapper{
public byte[] bytes;
}
And then javaGetData becomes:
int javaGetData(ByteArrayWrapper wrapper);
This is awful. Both in terms of the API signature and in terms of the jniGetData
method complexity.
Is there a better way?
The closest to what you have that will work is
native static int cppGetData(ByteBuffer bb);
This is not a lot better than what you have in that ByteBuffer is a wrapper for a byte[], but it uses built in class to do it. A limitation is that the underlying byte[] is not resizable but you can make it smaller by setting the limit
.
Another option is to use
native static int cppGetData(byte[][] bytes)
This allows you to return a different byte[].
Or you could
int[] num = { 0 };
native static byte[] cppGetData(int[] num)
or update fields of the object like
class CallsCppGetData {
int num;
byte[] bytes;
native void cppGetData(); // sets this.num and this.bytes.
}
The solution to returning more than one value is to use an object.
Either you
int[]
which has one element. While creating new classes is awful, so is having a method without than one result. ;)
If passing an object is so a problem, i see only one other solution: have two separate methods
jint prepareData();
jbyteArray getData();
Second one called only if the first one returns zero, as you specified. Of course this solution is not particularly atomic neither thredsafe as it requires storing a persistent data between calls at the C side. Unless you wrap both native calls in synchronized block on Java side. But many ubiquitous frameworks use this technique fearlessly for reporting some common internal state after other function calls. Win32 API GetLastError
comes to mind, though that one is threadsafe.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.