Преобразуйте char * в jstring в JNI, когда char * передается с использованием va_arg
Нужно ли преобразовать char * в jbyteArray, затем вызвать java String contructor для генерации jstring? Как еще это можно сделать? Пожалуйста помоги.
static int testhandler(void *arg, ...)
{
int i;
struct callback *cb = (struct callback *)arg;
JNIEnv *env = cb->env;
char *sig = cb->signature;
jint size = (jint) strlen(sig);
jint size1;
va_list arguments;
jobjectArray return_array;
jclass obj_class;
jbyteArray bytes;
jstring str;
obj_class = (*env)->FindClass(env, "java/lang/Object");
return_array = (*env)->NewObjectArray(env, size, obj_class, NULL);
va_start(arguments, arg);
for (i = 0; i < size; i++) {
jclass clazz;
jmethodID id;
jobject obj;
jobject encoding;
switch (sig[i]) {
case 'i': {
clazz = (*env)->FindClass(env, "java/lang/Integer");
id = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
obj = (*env)->NewObject(env, clazz, id, va_arg(arguments, uint32_t));
(*env)->SetObjectArrayElement(env, return_array, i, obj);
break;
}
case 'l': {
clazz = (*env)->FindClass(env, "java/lang/Long");
id = (*env)->GetMethodID(env, clazz, "<init>", "(J)V");
obj = (*env)->NewObject(env, clazz, id, va_arg(arguments, uint64_t));
(*env)->SetObjectArrayElement(env, return_array, i, obj);
break;
}
case 's': {
clazz = (*env)->FindClass(env, "java/lang/String");
size1 = (jint) strlen(va_arg(arguments, char *));
id = (*env)->GetMethodID(env, clazz, "<init>", "([BLjava/lang/String;)V");
encoding = (*env)->NewStringUTF(env, va_arg(arguments, char *));
bytes = (*env)->NewByteArray(env, size1);
(*env)->SetByteArrayRegion(env, bytes, 0, size1, (jbyte *)(va_arg(arguments, char *)));
str = (jstring)(*env)->NewObject(env, clazz, id , bytes);
obj = (*env)->NewObject(env, clazz, id, str);
(*env)->SetObjectArrayElement(env, return_array, i, obj);
break;
}
default: {
printf("unknown signature char '%c'\n", sig[i]);
}
}
}
va_end(arguments);
(*env)->CallVoidMethod(env, cb->handler, cb->id, return_array);
return 0;
}
Ответы
Ответ 1
Вы можете просто проверить документацию JNI api. Например. Здесь.
Вы найдете:
jstring NewStringUTF(JNIEnv *env, const char *bytes);
Итак, все, что вам нужно сделать, это примерно так:
char *buf = (char*)malloc(10);
strcpy(buf, "123456789"); // with the null terminator the string adds up to 10 bytes
jstring jstrBuf = (*env)->NewStringUTF(env, buf);
Ответ 2
Это зависит от характера вашей строки char *
. NewStringUTF
копии из 0-завершенной, модифицированной UTF-8 кодировки символов Unicode. NewString
копии с кодировкой , UTF-16 символов Unicode. Если у вас нет ни одного из них, вам необходимо выполнить преобразование.
Много кода, использующего NewStringUTF
, записывается с предположением, что строка NUL-terminated ASCII. Если это предположение верно, то оно будет работать, потому что модифицированная кодировка UTF-8 и кодировка ASCII будут вызывать одну и ту же последовательность байтов. Такой код должен быть четко прокомментирован для документирования ограничения на строковые данные.
Метод преобразования, который вы ссылаетесь на вызывающие Java-функции (например, String (байты [], кодировка Charset)) - хороший. Одна альтернатива (в Windows, я вижу, вы используете Visual Studio) MultiByteToWideChar. Другой вариант - iconv.
Итог: вы должны знать, что набор символов и кодировка, в котором используется ваша строка, а затем преобразовать ее в UTF-16 кодированный Unicode для использования в качестве строки Java.
Ответ 3
лучше вернуться byte[]
к java, а не к jstring
из-за разницы между строкой UTF в java и c string.it гораздо проще справиться с проблемой кодирования в java
в java:
byte[] otherString = nativeMethod("javastring".getBytes("UTF-8"))
в С++:
jbyte* javaStringByte = env->GetByteArrayElements(javaStringByteArray, NULL);
jsize javaStringlen = env->GetArrayLength(javaStringByteArray);
std::vector<char> vjavaString;
vjavaString.assign(javaStringByte , javaStringByte + tokenlen);
std::string cString(vjavaString.begin(), vjavaString.end());
//
// do your stuff ..
//
jsize otherLen = otherCString.size();
jbyteArray otherJavaString = env->NewByteArray(otherLen);
env->SetByteArrayRegion(otherJavaString , 0, otherLen , (jbyte*) &otherJavaString [0]);
env->ReleaseByteArrayElements(javaStringByteArray, javaStringByte , JNI_ABORT);
return otherJavaString ;
в java снова:
new String(otherString);