Is it necessary to convert char* to jbyteArray, then call java String's contructor to generate a jstring? How else can it be done? Please help.
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;
}
You could just check JNI api documentation. E.g. Here.
You will find:
jstring NewStringUTF(JNIEnv *env, const char *bytes);
So all you have to do it something like this:
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);
It depends on the nature of your char *
string. NewStringUTF
copies from a 0-terminated, modified UTF-8 encoding of Unicode characters. NewString
copies from a counted, UTF-16 encoding of Unicode characters. If you don't have either of those, you have to perform a conversion.
A lot of code using NewStringUTF
is written with the assumption that the string is NUL-terminated ASCII. If that assumption is correct then it will work because the modified UTF-8 encoding and the ASCII encoding would produce the same byte sequence. Such code should be clearly commented to document the restriction on the string data.
The conversion method you allude to—calling Java functions (e.g. String(byte[] bytes, Charset charset)) —is a good one. One alternative (in Windows, I see you are using Visual Studio) is MultiByteToWideChar. Another alternative is iconv.
Bottom line: You have to know what character set and encoding your string uses and then convert it to a UTF-16 encoded Unicode for use as a Java String.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With