开发者

Converting between jdoubleArray and vector<double> in a Java Native (JNI) method in C++

开发者 https://www.devze.com 2023-04-03 11:14 出处:网络
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 t

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消