web-dev-qa-db-ja.com

char *がva_argを使用して渡される場合、char *をJNIのjstringに変換します

Char *をjbyteArrayに変換してから、Java Stringコンストラクタを呼び出して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;
}
12
user2358330

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);
34
mkaes

それはあなたの性質に依存しますchar * ストリング。 NewStringUTFは、Unicode文字の0で終了し、変更されたUTF-8エンコーディングからコピーします。 NewStringは、Unicode文字のカウントされたUTF-16エンコーディングからコピーします。これらのいずれもない場合は、変換を実行する必要があります。

NewStringUTFを使用する多くのコードは、文字列がNULで終了するASCIIであるという前提で記述されています。その仮定が正しい場合、修正されたUTF-8エンコーディングとASCIIエンコーディングは同じバイトシーケンスを生成するため、機能します。このようなコードは、文字列データの制限を文書化するために明確にコメントする必要があります。 。

想定している変換方法-呼び出しJava関数(例String(byte [] bytes、Charset charset))—良い方法です。1つの代替手段(Windowsでは、Visual Studioを使用しているようです)は MultiByteToWideChar です。別の代替手段はiconvです。

結論:文字列が何を使用しているか文字セットとエンコーディングを把握し、UTF-16エンコードに変換する必要があります。 Java文字列として使用するUnicode。

7
Tom Blodget

Javaとc文字列のUTF文字列が異なるため、jstringではなくbyte[]をJavaに戻す方が適切です。 。それはJavaでのエンコーディングの問題を処理する方がはるかに簡単です

javaで:

byte[] otherString = nativeMethod("javastring".getBytes("UTF-8"))

c ++の場合:

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);
3
zyanlu