Converting between jdoubleArray and vector<double> in a Java Native (JNI) method in C++
I have a C++ dll that contains methods that I need to use in a Java program. I've been through all the Sun documentation on JNI, and numerous tutorials I found on the web, and I can't seem to find the problem with my code. In fact, a fair portion of the code is cut and pasted from various tutorials and the Sun website.
My specific problem is as follows: My C++ native method receives a jdoubleArray from my Java program, which needs to be mapped to a c++ vector that can then be passed to a method in the C++ dll. The method in the dll returns another vector, that then needs to be mapped to a new jdoubleArray, and returned to the Java program. The problem seems to be that I'm not performing the mapping correctly.
The code I have is as follows (I've removed the call to the dll method for simplicity):
JNIEXPORT jdoubleA开发者_Go百科rray JNICALL Java_jniarraypassing_JNIArrayPassing_passAndReturn(JNIEnv *env, jclass jcls, jdoubleArray arr)
{
//First get a pointer to the elements within the jdoubleArray
jsize len = env->GetArrayLength(arr);
jboolean isCopy1;
jdouble *body = env->GetDoubleArrayElements(arr, &isCopy1);
//Create the vector<double> and reserve enough memory for mapping
std::vector<double> newvector;
newvector.reserve(len);
//Copy the contents of the jdoubleArray to the vector<double>
for (int i=0; i<len; i++)
{
newvector.push_back(body[i]);
}
//Release the pointer to the jdoubleArray
if (isCopy1 == JNI_TRUE)
{
env->ReleaseDoubleArrayElements(arr, body, JNI_ABORT);
}
//Call the dll method here....
jdoubleArray output = env->NewDoubleArray(newvector.size());
jboolean isCopy2;
jdouble* destArrayElems = env->GetDoubleArrayElements(output, &isCopy2);
for (int i=0; i<newvector.size(); i++)
{
destArrayElems[i] = newvector[i];
}
if (isCopy2 == JNI_TRUE)
{
env->ReleaseDoubleArrayElements(arr, destArrayElems, 0);
}
return output;
}
When I output the contents of body[i] to the console, I get a series of numbers that look remarkably like Hexadecimal values (e.g. 003DFBE0), but they are all the same, so I don't think they can be memory addresses.
The contents of the returned jdoubleArray consists entirely of default double values (i.e. 0.0), which I suspect is because the values from the original jdoubleArray are invalid?
What I need to find out, is
Any help would be appreciated!
According to the documentation, GetDoubleArrayElements
may return a
pointer to a copy, rather than a pointer to the actual data; this is why
you need to call ReleaseDoubleArrayElements
, for example. If you're
copying, then it's normal that you don't see the values you've written.
If you're using std::vector
, I'd use GetDoubleArrayRegion
and
SetDoubleArrayRegion
:
jsize size = env->GetArrayLength( arr );
std::vector<double> input( size );
env->GetDoubleArrayRegion( arr, 0, size, &input[0] );
// ...
jdoubleArray output = env->NewDoubleArray( results.size() );
env->SetDoubleArrayRegion( output, 0, results.size(), &results[0] );
I think this is the only way to initialize an output array.
精彩评论