jni 字符串的梳理 2 字符串的处理操作

Posted luzhouxiaoshuai

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jni 字符串的梳理 2 字符串的处理操作相关的知识,希望对你有一定的参考价值。

我们实现下面的一个功能:

1、首先在java层传递一个字符串到c层,c层首先将jstring转换成char*类型,然后将两个字符串相加,然后再再将char*类型转换成jstring,在上层显示出来

我们来看底层程序的代码:

//
// Created by wei.yuan on 2017/6/13.
//
#include <jni.h>
#include <string.h>
#include <pthread.h>
#include "im_weiyuan_com_jni_Sdk.h"
#include "im_weiyuan_com_jni_Sdk_OnSubProgressListener.h"
#include "im_weiyuan_com_jni_Sdk_SdkHodler.h"
JavaVM *g_VM;
jobject g_obj;
#include <jni.h>
#include <string.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
#include <assert.h>
#include <android\log.h>
#include <errno.h>
#include <pthread.h>
#include <android/log.h>


#define LOG_TAG "Native"
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)

/*方法三,调用C库函数,*/
char* join(char *s1, char *s2)
{
    char *result = malloc(strlen(s1)+strlen(s2)+1);//+1 for the zero-terminator
    //in real code you would check for errors in malloc here
    if (result == NULL) exit (1);

    strcpy(result, s1);
    strcat(result, s2);

    return result;
}

/*1、第一步将输入的jstring类型转换成char*类型
 * 2、将两个char*类型的字符串拼接起来
 * 3、将cha*类型的转换成jstring类型,返回给java层
 *
 *
 *
 *
 */
JNIEXPORT jstring JNICALL Java_im_weiyuan_com_jni_Sdk_getStringFromC
        (JNIEnv * env, jobject jobj, jstring jstr){
    const jbyte *str;

    str = (*env)->GetStringUTFChars(env, jstr, NULL);

    if (str == NULL) {

        return NULL; /* OutOfMemoryError already thrown */

    }
    LOGE("123456789:%s\n",str);
    char *hello = "I from C++";

    char*result = NULL;
    result = join(str,hello);

    LOGE("123456789 result len is :%d\n",strlen(result));
    (*env)->ReleaseStringUTFChars(env, jstr, str);
    //malloc申请的内存记得要是否
    if(result !=NULL){
        LOGE("123456789 result len is free\n");
        free(result);
    }
    return (*env)->NewStringUTF(env, result);
}

这里一定要注意strcat和strcpy的使用方式:

 上面的代码还有一个致命的问题:

要为所需的内存分配足够的空间,否则会出现严重的错误。同时,分配的时候若想使用strlen()来确定内存大小时,要注意进行转换,因为内存中是以字节数来计算大小的,而strlen返回的只是字符串长度,如strlen("abc")返回的3,但是可能每个字符占两字节(不同系统有所不同),即内存大小应该为6。

所以上面的代码应该写成下面的形式:

/*方法三,调用C库函数,*/
char* join(char *s1, char *s2)
{
    char *result = malloc((strlen(s1)+strlen(s2)+1)* sizeof(char));//+1 for the zero-terminator
    //in real code you would check for errors in malloc here
    if (result == NULL) exit (1);

    strcpy(result, s1);
    strcat(result, s2);

    return result;
}

 

头文件:#include <string.h>


strcat() 函数用来连接字符串,其原型为:
    char *strcat(char *dest, const char *src);

【参数】dest 为目的字符串指针,src 为源字符串指针。

strcat() 会将参数 src 字符串复制到参数 dest 所指的字符串尾部;dest 最后的结束字符 NULL 会被覆盖掉,并在连接后的字符串的尾部再增加一个 NULL。

注意:dest 与 src 所指的内存空间不能重叠,且 dest 要有足够的空间来容纳要复制的字符串。

【返回值】返回dest 字符串起始地址。

【实例】连接字符串并输出。
#include <stdio.h>
#include <string.h>

int main ()
{
    char str[80];
    strcpy (str,"these ");
    strcat (str,"strings ");
    strcat (str,"are ");
    strcat (str,"concatenated.");
    puts (str);
    return 0;
}

 

错误案例一:

在实际开放中,我们可能会用到strcat拼接两个字符串,例如

char a[6] = "hello";
char b[6] = "world";
strcat(a,b);
free(a);
free(b);

此时会出现越界情况,由于a只有6个字符的空间,拼接后超出了本身空间大小,因此会报错,
所以需要用realloc重新给a分配足够的空间来存储新的字符串。

在使用指针时,需要时刻注意空间的分配,空间的大小,空间的释放等问题

 

以上是关于jni 字符串的梳理 2 字符串的处理操作的主要内容,如果未能解决你的问题,请参考以下文章

混合编程jni 第六篇之native 中字符串和数组的操作

Android JNI开发五: JNI字符串的处理

Android JNI开发五: JNI字符串的处理

JNI内两种方式从C/C++中传递一维二维三维数组数据至Java层详细梳理

Android 安装包优化使用 lib7zr.so 动态库处理压缩文件 ( jni 中 main 函数声明 | 命令行处理 | jni 调用 lib7zr.so 函数库处理压缩文件完整代码 )(代码片

JNI/NDK开发指南——字符串处理