Как вызвать метод Java из C ++ (Java возвращает String [])? - PullRequest
3 голосов
/ 24 сентября 2011

Насколько я знаю, я не могу вызвать метод из C ++, который будет возвращать из строкового массива Java, поэтому единственным решением для этого является метод вызова цикла, который возвращает элементы массива по одному, но как я могу сохранить их в C ++ массив

В Java у меня есть метод:

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

и в 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);
}

но когда i = 1, я получаю ошибку нарушения памяти в Java. Как правильно скопировать данные из полученных строк в char * args[10]? Длина каждой строки, передаваемой с Java, составляет около 3-5 символов.

1 Ответ

6 голосов
/ 24 сентября 2011

Предполагая, что опубликованный вами фрагмент кода C ++ завершен, вы получаете нарушение прав доступа, поскольку вам необходимо выделить args[i] перед копированием значения в него - args[i] = new char[ len + 1 ] подойдет.

Вы можетена самом деле вызовите метод из C ++, который возвращает массив строк Java, предположим, что ваш метод был:

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

Тогда на нативной стороне вы сможете сделать что-то вроде:

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 );
}

Я не пытался скомпилировать приведенный выше фрагмент, поэтому может быть одна или две ошибки, но это должно быть хорошей отправной точкой.Я оставил код, используя массив char * и собственные строки, поэтому в какой-то момент код должен будет вызывать delete[] для каждого члена массива и самого массива.В конечном итоге может оказаться проще использовать std::vector и std::string для управления памятью в зависимости от того, как будут использоваться предоставленные строки.

...