JNI编程四:java跟JNI字符串传递

目录

  • 前言
  • 一、java层向jni层传递中文字符串的转码操作
  • 二、jni层向java层传递中文字符串的转码操作


前言

java中的中文字符使用的编码方式是根据系统默认编码方式,一般使用的是GB2312的编码方式,jni中的中文字符采用的是unicode的编码方式。所以在字符传递的时候会出现乱码情况。

一、java层向jni层传递中文字符串的转码操作

java层向jni传递中文字符的时候,我们可以利用windows.h给我们封装好的函数来操作。

JniMain.java

public class JniMain {

    static{
        System.loadLibrary("JNI_Demo1");
    }
    
    //----------------------向jni层传递字符串--------------------
    public native String chineseChars(String str);
    //---------------------------------------------
    
    
    public static void main(String[] args) {
        
        JniMain jm = new JniMain();
    
        String str = jm.chineseChars("德玛西亚"); 
        
        System.out.println("java "+ str);
        
    }
}

jni_impl.c

#include "stdafx.h"

#include "JniMain.h"
#include <string.h>
#include <Windows.h>

/*
* Class:     JniMain
* Method:    chineseChars
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_JniMain_chineseChars
(JNIEnv * env, jobject jobj, jstring in){
    
        //iscp代表的是string转char的时候是否从新开辟的内存copy的一份
    jboolean iscp;
    char * c_str = (*env)->GetStringChars(env, in, &iscp);
    if (iscp == JNI_TRUE)
    {
        printf("is copy: JNI_TRUE\n");
    }
    else if (iscp == JNI_FALSE)
    {
        printf("is copy: JNI_FALSE\n");
    }

    int length = (*env)->GetStringLength(env, in);
    const jchar * jcstr = (*env)->GetStringChars(env, in, NULL);
    if (jcstr == NULL) {
        return NULL;
    }
    //jchar -> char
    char * rtn = (char *)malloc(sizeof(char)* 2 * (length + 1));
    memset(rtn, 0, sizeof(char)* 2 * (length + 1));
    int size = 0;
    //windows提供的字符串转码的操作
    size = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)jcstr, length, rtn, sizeof(char)* 2 * (length + 1), NULL, NULL);
    /*if (size <= 0)
    {
    printf("size: 0 \n", rtn);
    return NULL;
    }*/
    printf("jni string: %s\n", rtn);
    if (rtn != NULL) {
        free(rtn);
        rtn = NULL;
    }
    if (iscp == JNI_TRUE)
    {
        (*env)->ReleaseStringChars(env, in, c_str);// JVM 使用。通知JVM c_str 所指的空间可以释放了
    }

      return NULL;
}

jni_impl.c的JNICALL Java_JniMain_chineseChars函数是将java层传递的字符串能转换成jni能识别的字符串。执行结果:

在这里插入图片描述


二、jni层向java层传递中文字符串的转码操作

jni层向java层传递字符串时可以使用JNIEnv所指向的结构体封装的函数来调用java中String对象封装的字符串转码功能。

jni_impl.c

#include "stdafx.h"

#include "JniMain.h"
#include <string.h>
#include <Windows.h>

/*
* Class:     JniMain
* Method:    chineseChars
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_JniMain_chineseChars
(JNIEnv * env, jobject jobj, jstring in){
    
       char *c_str2 = "诺克萨斯";
    jclass str_cls = (*env)->FindClass(env, "java/lang/String");
    jmethodID jmid = (*env)->GetMethodID(env, str_cls, "", "([BLjava/lang/String;)V");
    
    //jstring -> jbyteArray
    jbyteArray bytes = (*env)->NewByteArray(env, strlen(c_str2));
    // 将Char * 赋值到 bytes
    (*env)->SetByteArrayRegion(env, bytes, 0, strlen(c_str2), c_str2);
    jstring charsetName = (*env)->NewStringUTF(env, "GB2312");

    return (*env)->NewObject(env, str_cls, jmid, bytes, charsetName);

}

其实上面的代码就是jvm反射调用java中的 new String(“诺克萨斯”,“GB2312”)


你可能感兴趣的:(JNI/NDK,JNI)