3

As far as I know I can't call method from C++ that will return from Java string array, so only solution for this is loop call method that will return array elements on by one, but how can I store them in C++ array?

In Java I have method:

public static String getData(int index){ return arry[index]; }

and in C++:

char * args[10];
for (int i = 0; i < arrayLength; i ++) {
    jmethodID mid = env->GetStaticMethodID(INF.cls_JSox, "getData",(I)Ljava/lang/String;");
    jobject result = env->CallStaticObjectMethod(cls, mid, num, i);
    const char *nativeString = env->GetStringUTFChars( (jstring) result, 0);
    const size_t len = strlen(nativeString);
    cout << "copying... \n";
    strncpy(args[i], nativeString, len);
    env->ReleaseStringUTFChars( (jstring)result, nativeString);
}

but when i = 1 I'm getting memory violation error in Java. How can I correctly copy data from received strings to the char * args[10]? The length of every string passed from Java is about 3-5 chars.

2
  • It's absolutely possible to use JNI to call a Java method that returns a string array. Commented Sep 24, 2011 at 14:57
  • Does 'INF.cls_JSox' in 'GetStaticMethodID' refer to the same class as 'cls' in CallStaticObjectMethod ? Commented Sep 26, 2011 at 6:11

1 Answer 1

6

Assuming that the C++ code snippet you posted is complete, you are getting an access violation because you need to allocate args[i] before copying a value into it - a args[i] = new char[ len + 1 ] would do.

You can actually call a method from C++ that returns a Java string array, assume your method was:

public static String[] getData() { return array; }

Then on the native side you should be able to do something like:

jmethodID method = env->GetStaticMethodID( cls, "getData", "()[Ljava/lang/String;" );
jarray    data   = (jarray) env->CallStaticObjectMethod( cls, method );

// assumption: the result of getData() is never null
jsize const length = env->GetArrayLength( data );

// assumption: the String[] is always of length > 0
char** args = new char*[ length ];

for( jsize index(0); index < length; ++index )
{
    jstring element = (jstring) env->GetObjectArrayElement( data, index );

    // assumption: there are no null strings in the array
    char  const* nativeString = env->GetStringUTFChars( element, 0 );
    jsize const  nativeLength = strlen( nativeString );

    args[index] = new char[ nativeLength + 1 ];
    strncpy( args[index], nativeString, nativeLength );

    env->ReleaseStringUTFChars( element, nativeString );
    env->DeleteLocalRef( element );
}

I haven't tried to compile the above snippet so there might be an error or two, but it should be an ok starting point. I've left the code using a char* array and native strings, so at some point the code is going to have to call delete[] on each member of the array and on the array itself. It may end up ultimately simpler using std::vector and std::string for memory management depending on how the supplied strings are going to be used.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.