Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/399.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/223.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 调用静态JNI方法从C++;_Java_Android_C++_Android Ndk_Java Native Interface - Fatal编程技术网

Java 调用静态JNI方法从C++;

Java 调用静态JNI方法从C++;,java,android,c++,android-ndk,java-native-interface,Java,Android,C++,Android Ndk,Java Native Interface,我试图在Android中调用以下java方法 public static String getLevelFile(String levelName) { /*body*/} 从C++使用以下JNI代码 JniMethodInfoJavaApi methodInfo; if (! getStaticMethodInfo(methodInfo, "getLevelFile", "(Ljava/lang/String;)Ljava/lang/String;")) {

我试图在Android中调用以下java方法

public static String getLevelFile(String levelName) { /*body*/}
从C++使用以下JNI代码

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(“调用getLevelFile”)打印良好,然后崩溃。我可以从同一个类中执行其他
CallStaticVoidMethod()
s,但不能执行这个类。知道我做错了什么吗?

您不能直接将nul终止的字符串(从
c_str()
返回)作为参数传递给Java/JNI方法


要将其传递给该方法,请从以nul结尾的字符串创建一个
jstring
(例如使用
NewStringUTF
)并将其传递给该方法。

幸运的是,Java和Android都使用Unicode字符集。然而,Android(默认情况下)使用UTF-8编码,JNI本质上不支持UTF-8编码。尽管如此,Java类完全能够在字符集编码之间进行转换。
lang.java.String
构造函数允许您指定字符集/编码或使用操作系统默认值,当然,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;
JniMethodInfoJavaApi methodInfo;
如果(!getStaticMethodInfo(methodInfo,“getLevelFile”,“([B)[B”))
{
返回std::字符串(“”);
}
LOGD(“调用getLevelFile”);
int nameLength=levelName.length();
jbyterarray nameBytes=methodInfo.env->NewByteArray(nameLength);
methodInfo.env->SetByteArrayRegion(nameBytes,0,nameLength,reinterpret_cast(levelName.c_str());
jbyteArray returnString=(jbyteArray)methodInfo.env->CallStaticObjectMethod(methodInfo.classID,methodInfo.methodID,nameBytes);
LOGD(“从getLevelFile返回”);
methodInfo.env->DeleteLocalRef(methodInfo.classID);
methodInfo.env->DeleteLocalRef(nameBytes);
int returnLength=methodInfo.env->GetArrayLength(returnString);
std::字符串数据;
数据保留(返回长度);
methodInfo.env->GetByteArrayRegion(returnString,0,returnLength,reinterpret_cast(&data[0]);
methodInfo.env->DeleteLocalRef(returnString);
LOGD(“返回液位数据”);
返回数据;

自从我使用JNI已经有一段时间了,但是我相当确定您不能通过
c_str()的结果
到Java方法,但需要创建一个
jstring
来传递。是的。使用
NewStringUTF
NewString
从MUTF-8或UTF-16创建字符串。谢谢@JoachimIsaksson。它起作用了。如果你把它作为一个答案,我很乐意标记为正确并投票。