在 android studio JNI 函数中使用 jint 和 jstring

using jint and jstring in android studio JNI function

我正在 Android Studio 中开发一个 JNI 示例,目标是生成一个随机值并将其传递给一个本地函数,该函数将计算其平方和 return 结果这种格式 ( Number/Square ).

我将 jint 编号作为函数的参数传递,但结果完全错误(显示的结果完全错误)。 这是我的代码:

按钮生成数字并调用本机函数:

Button ButtonP = (Button)findViewById(R.id.button3);
        ButtonP .setOnClickListener(
                new View.OnClickListener()
                {
                    public void onClick(View view)
                    {
                        Random r = new Random();
                        Integer valeur = 1 + r.nextInt(10 - 1);
                        Log.i("Tag", "Random Value BARRAK " + valeur);
                        TextView tv = (TextView) findViewById(R.id.sample_text);
                        tv.setText(stringFromJNIStop(valeur));
                    }
                });

原生函数:

public native String stringFromJNIStop(Integer nombre);

cpp文件中函数的实现:

extern "C"
JNIEXPORT jstring JNICALL
Java_fr_utbm_testjniapplication1_MainActivity_stringFromJNIStop(
        JNIEnv *env,
        jobject, /* this */
        jint nombre) {
    jint CarreNombre = nombre*nombre;

    //Convertir le carré en un jstring
    char bufCarreNombre[64];
    sprintf(bufCarreNombre, "%d", CarreNombre);  // error checking omitted
    jstring jStringCarre = (*env).NewStringUTF(bufCarreNombre);
    //Le convertir en un char *
    const char *strCarre= (*env).GetStringUTFChars(jStringCarre,0);

    //Convertir le nombre en un jstring
    char bufNombre[64];
    sprintf(bufNombre, "%d", nombre);  // error checking omitted
    jstring jStringNombre = (*env).NewStringUTF(bufNombre);
    //Le convertir en char *
    const char *strNombre= (*env).GetStringUTFChars(jStringNombre,0);

    //Concaténer les deux
    char *concatenated;
    concatenated = (char *) malloc(strlen(strNombre) + strlen("/") + strlen(strCarre) + 1);
    strcpy(concatenated, strNombre);
    strcat(concatenated, "/");
    strcat(concatenated, strCarre);

    /* Create java string from our concatenated C string */
    jstring retval = (*env).NewStringUTF(concatenated);

    //need to release this string when done with it in order to
    //avoid memory leak
    (*env).ReleaseStringUTFChars(jStringNombre,strNombre);
    (*env).ReleaseStringUTFChars(jStringCarre,strCarre);
    /* Free the memory in concatenated */
    free(concatenated);
    return retval;

}

经过一番反思,问题解决了,实际上为了使用jint实现JNI功能,我们必须在JAVA部分采用精确的转换规则,而不是声明随机值作为整数,我们必须将其声明为 long !所以我们必须按如下方式工作:

long valeur = 1 + r.nextInt(10 - 1);

The Native function:

public native String stringFromJNIStop(Integer nombre);

The implementation of the function in the cpp file:

extern "C"
JNIEXPORT jstring JNICALL
Java_fr_utbm_testjniapplication1_MainActivity_stringFromJNIStop(
    JNIEnv *env,
    jobject, /* this */
    jint nombre) {

这与您的 Java 不一致。您在 Java 中将它从 int 更改为 Integer 而没有重新生成您的 .h 文件,或者您更改或发明了您的 .h 文件而没有参考您的 .java 文件;或者您的 .cpp 文件与您的 .h/.hpp 文件不一致。不要这样做。使用 javah 生成您的 .h/.hpp 文件,并在每次更改 .java 文件中的本地声明时重做,并确保您的 .cpp 文件与 .cpp 文件一致。 h/.hpp 文件。应该是:

extern "C"
JNIEXPORT jstring JNICALL
Java_fr_utbm_testjniapplication1_MainActivity_stringFromJNIStop(
    JNIEnv *env,
    jobject, /* this */
    jobject nombre) {

其中 nombre 指的是 Integer。然而,将您的 Java 本机方法定义为:

会更好,而且总是会更好
public native String stringFromJNIStop(int nombre);

现在将与您现有的 .cpp 一致。

您的 .cpp 也应该 #include 您的 .h/.hpp。那么您就不需要 extern "C"JNI_EXPORTJNI_CALL,并且编译器可能已经检测到 .cpp 和 .h/.hpp 之间的签名不一致。