如何通过 JNI 将 java CharSequence 转换为 C++ char*
How to convert java CharSequence to c++ char* through JNI
我觉得这应该有一个简单的答案,因为我可以使用 java String
轻松完成,但是 CharSequence
出了点问题。我的 java 代码初始化一个 cppGenerator
,将一个 functionBlock object
传递给它的 generateImplementation method
,并且 returns 传递一个 CharSequence
。这是我的代码:
jobject fBlock = env->CallObjectMethod(structuredTextModel, getFunction);
jclass CPPGenerator = lookForClass(env, "Path/CPPGenerator");
jobject CPPGeneratorImpl = invokeClassObj(env, CPPGenerator);
jmethodID generateImplementation = env->GetMethodID(CPPGenerator, "generateImplementation", "(LPath/FunctionBlock;)Ljava/lang/CharSequence;");
jobject mid = env->CallObjectMethod(CPPGeneratorImpl, generateImplementation, fBlock);
jstring jresult = (jstring)mid;
char* result = (char*)env->GetStringUTFChars(jresult, 0);
这个逻辑在我使用 String
时对我有用,但是这个函数 returns 是 CharSequence
。没有 类、对象或方法返回 null。程序在 jni.h
尝试调用 GetStringUTFChars
时崩溃。所以我知道我不能将此方法用于 CharSequence。是否只缺少一个 jni 方法,或者我是否必须为 CharSequence 做一些完全不同的事情?
您不能只将 mid
转换为 jstring
并调用 GetStringUTFChars
(因为 mid
可能不是 String
,这似乎是案子)。对于 CharSequence
s 没有像 GetStringUTFChars
这样的方便方法,就像对于 String
s.
你必须以不方便的方式调用 charAt
:
jclass cCharSequence = env->FindClass("java/lang/CharSequence");
jmethodID mLength = env->GetMethodID(cCharSequence, "length", "()I");
jmethodID mCharAt = env->GetMethodID(cCharSequence, "charAt", "(I)C");
int length = env->CallIntMethod(mid, mLength);
std::string str;
str.reserve(length);
for(int i = 0; i < length; i++) {
str += env->CallCharMethod(mid, mCharAt, i);
}
// use 'str.c_str()'...
为什么不直接使用toString
?
jclass clzCharSequence = env->GetObjectClass(mid);
jmethodID toString = env->GetMethodID(clzCharSequence, "toString", "()Ljava/lang/String;");
jobject s = env->CallObjectMethod(mid, toString);
const char* cstr = env->GetStringUTFChars(static_cast<jstring>(s), NULL);
// do something with cstr
env->ReleaseStringUTFChars(static_cast<jstring>(s), cstr);
我觉得这应该有一个简单的答案,因为我可以使用 java String
轻松完成,但是 CharSequence
出了点问题。我的 java 代码初始化一个 cppGenerator
,将一个 functionBlock object
传递给它的 generateImplementation method
,并且 returns 传递一个 CharSequence
。这是我的代码:
jobject fBlock = env->CallObjectMethod(structuredTextModel, getFunction);
jclass CPPGenerator = lookForClass(env, "Path/CPPGenerator");
jobject CPPGeneratorImpl = invokeClassObj(env, CPPGenerator);
jmethodID generateImplementation = env->GetMethodID(CPPGenerator, "generateImplementation", "(LPath/FunctionBlock;)Ljava/lang/CharSequence;");
jobject mid = env->CallObjectMethod(CPPGeneratorImpl, generateImplementation, fBlock);
jstring jresult = (jstring)mid;
char* result = (char*)env->GetStringUTFChars(jresult, 0);
这个逻辑在我使用 String
时对我有用,但是这个函数 returns 是 CharSequence
。没有 类、对象或方法返回 null。程序在 jni.h
尝试调用 GetStringUTFChars
时崩溃。所以我知道我不能将此方法用于 CharSequence。是否只缺少一个 jni 方法,或者我是否必须为 CharSequence 做一些完全不同的事情?
您不能只将 mid
转换为 jstring
并调用 GetStringUTFChars
(因为 mid
可能不是 String
,这似乎是案子)。对于 CharSequence
s 没有像 GetStringUTFChars
这样的方便方法,就像对于 String
s.
你必须以不方便的方式调用 charAt
:
jclass cCharSequence = env->FindClass("java/lang/CharSequence");
jmethodID mLength = env->GetMethodID(cCharSequence, "length", "()I");
jmethodID mCharAt = env->GetMethodID(cCharSequence, "charAt", "(I)C");
int length = env->CallIntMethod(mid, mLength);
std::string str;
str.reserve(length);
for(int i = 0; i < length; i++) {
str += env->CallCharMethod(mid, mCharAt, i);
}
// use 'str.c_str()'...
为什么不直接使用toString
?
jclass clzCharSequence = env->GetObjectClass(mid);
jmethodID toString = env->GetMethodID(clzCharSequence, "toString", "()Ljava/lang/String;");
jobject s = env->CallObjectMethod(mid, toString);
const char* cstr = env->GetStringUTFChars(static_cast<jstring>(s), NULL);
// do something with cstr
env->ReleaseStringUTFChars(static_cast<jstring>(s), cstr);