我试图在Android中调用以下java方法
public static String getLevelFile(String levelName) { /*body*/}
使用以下jni代码从c ++中
JniMethodInfoJavaApi methodInfo;
if (! getStaticMethodInfo(methodInfo, "getLevelFile", "(Ljava/lang/String;)Ljava/lang/String;"))
{
return std::string("");
}
LOGD("calling getLevelFile");
jstring returnString = (jstring) methodInfo.env->CallStaticObjectMethod(methodInfo.classID, methodInfo.methodID, levelName.c_str());
LOGD("returned from getLevelFile");
methodInfo.env->DeleteLocalRef(methodInfo.classID);
const char *js = methodInfo.env->GetStringUTFChars(returnString, NULL);
std::string cs(js);
methodInfo.env->ReleaseStringUTFChars(returnString, js);
LOGD("returning Level data");
执行CallStaticMethodObject()
时应用崩溃了。我已使用javap
验证方法签名是否正确。并且LOGD("calling getLevelFile");
打印正常,然后崩溃。我可以从同一个班级做其他CallStaticVoidMethod()
但不能做这个。我有什么想法吗?
答案 0 :(得分:5)
你很幸运,Java和Android都使用Unicode字符集。但是,Android(默认情况下)使用UTF-8编码,JNI并不支持这种编码。尽管如此,Java类完全能够在字符集编码之间进行转换。 lang.java.String
构造函数允许您指定字符集/编码或使用OS-default,当然,在Android上,它被编码为UTF-8。
为了更容易(我更喜欢用Java编码,最小化调用JNI库的代码),创建方法的重载并在Java中执行一些实现:
private static byte[] getLevelFile(byte[] levelName) {
return getLevelFile(new String(levelName)).getBytes();
}
现在JNI代码只需处理jbytearray,包括参数和返回值:
JniMethodInfoJavaApi methodInfo;
if (! getStaticMethodInfo(methodInfo, "getLevelFile", "([B)[B"))
{
return std::string("");
}
LOGD("calling getLevelFile");
int nameLength = levelName.length();
jbyteArray nameBytes = methodInfo.env->NewByteArray(nameLength);
methodInfo.env->SetByteArrayRegion(nameBytes, 0, nameLength, reinterpret_cast<const jbyte*>(levelName.c_str()));
jbyteArray returnString = (jbyteArray) methodInfo.env->CallStaticObjectMethod(methodInfo.classID, methodInfo.methodID, nameBytes);
LOGD("returned from getLevelFile");
methodInfo.env->DeleteLocalRef(methodInfo.classID);
methodInfo.env->DeleteLocalRef(nameBytes);
int returnLength = methodInfo.env->GetArrayLength(returnString);
std::string data;
data.reserve(returnLength);
methodInfo.env->GetByteArrayRegion(returnString, 0, returnLength, reinterpret_cast<jbyte*>(&data[0]));
methodInfo.env->DeleteLocalRef(returnString);
LOGD("returning Level data");
return data;
答案 1 :(得分:3)
您无法直接将以空字符结尾的字符串(从c_str()
返回)作为参数传递给Java / JNI方法。
要将其传递给方法,请从nul终止的字符串创建jstring
(例如使用NewStringUTF
)并传递它。