#include
<stdio.h>
#include
<string.h>
#include
<android/log.h>
#ifndef LOGV
#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE,
"https2auth", __VA_ARGS__)
#endif
#ifndef LOGD
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG
, "https2auth",
__VA_ARGS__)
#endif
#ifndef LOGI
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO
, "https2auth",
__VA_ARGS__)
#endif
#ifndef LOGW
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN
, "https2auth",
__VA_ARGS__)
#endif
#ifndef LOGE
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR
, "https2auth",
__VA_ARGS__)
#endif
#include
<jni.h>
#ifndef IN
#define IN
#endif
#ifndef OUT
#define OUT
#endif
// 由 Java
String 转为指定编码的 char 数组
//
注:调用者再传入 puiOutputStringLen 参数指针值时,一定要是
unsigned int 类型的变量指针,
// 如果将 unsigned char
类型的变量地址强制转换后传入,会在传出值时覆盖四个字节,就会出现内存越界的问题!!!
int
jstring2pchar( IN
JNIEnv*
env,
// JNI
本地接口指针
IN
jstring
jniInputString,
//
Java层传下来的字符串
IN
const char*
pcEncoding,
// 可以指定转换为的编码
OUT
char* const
pcOutputString,
// 返回转换后的字符串,若为 NULL 仅是取所需字节个数
IN OUT
unsigned int* const puiOutputStringLen ) //
返回转换后的字节个数(不含‘\0’)
{
//
返回值
int
iResult = 0; // 零为成功
// Java
字符串的类和获取字节的方法ID
jclass
jniStringClass =
NULL;
jmethodID jniGetBytesMethodID = NULL;
//
指定转换字符串时用的编码格式
jstring
jniEncoding = NULL;
// 取得
字符串 转换成 字节数组
jbyteArray jniByteArray = NULL;
// 取得
字符串 转换成 字节数组 的字节个数
jsize
jniByteArraySize = 0;
// 基本类型
- 字节数组
jbyte*
jniPrimitiveByteArray = NULL;
do //
非循环,只是为了减少分支缩进
{
// 要转换的字符串或要传出字节个数的变量指针为 NULL
时
if ( ( NULL == env )
||
( NULL == jniInputString )
||
( NULL == pcOutputString )
||
( NULL == puiOutputStringLen )
)
{
__android_log_print(
ANDROID_LOG_INFO,
"jstring2pchar",
"Parameter
is invalid!" );
iResult = -1;
break;
}
// 指定字符串编码格式
if ( NULL
== pcEncoding )
{
jniEncoding =
(*env)->NewStringUTF( env, "utf-8"
);
}
else
{
jniEncoding
=(*env)->NewStringUTF( env, pcEncoding
);
}
if ( NULL == jniEncoding
)
{
__android_log_print(
ANDROID_LOG_INFO,
"jstring2pchar",
"Call
NewStringUTF to get specific encoding failed!" );
iResult = -2;
break;
}
// 获取 Java String 类和回调方法 I
D信息,
//
也可以用全局变量记下来,免得浪费时间重复执行。
jniStringClass =
(*env)->FindClass( env,
"java/lang/String"
);
if ( NULL == jniStringClass
)
{
__android_log_print(
ANDROID_LOG_INFO,
"jstring2pchar",
"Call
FindClass to get java/lang/String failed!" );
iResult = -3;
break;
}
// 得到 String 类的 getBytes
方法
jniGetBytesMethodID =
(*env)->GetMethodID( env,
jniStringClass,
"getBytes",
"(Ljava/lang/String;)[B" );
if ( NULL ==
jniGetBytesMethodID )
{
__android_log_print(
ANDROID_LOG_INFO,
"jstring2pchar",
"Call
GetMethodID to get getBytes method failed!" );
iResult = -4;
break;
}
// 从 字符串 中得到指定编码的
字节数组
jniByteArray =
(jbyteArray)(*env)->CallObjectMethod(
env,
jniInputString,
jniGetBytesMethodID,
jniEncoding
);
if ( NULL == jniByteArray
)
{
__android_log_print(
ANDROID_LOG_INFO,
"jstring2pchar",
"Call
NewStringUTF to get specific encoding failed!" );
iResult = -5;
break;
}
// 取得 字符串 转换成 字节数组
的字节个数
jniByteArraySize =
(*env)->GetArrayLength( env, jniByteArray
);
if ( 0 >=
jniByteArraySize )
{
__android_log_print(
ANDROID_LOG_INFO,
"jstring2pchar",
"Call
GetArrayLength to get array length failed!" );
iResult = -6;
break;
}
// 返回原始数组的实体,需要对应调用
ReleaseByteArrayElements 来释放返回值
jniPrimitiveByteArray =
(*env)->GetByteArrayElements( env,
jniByteArray,
NULL ); //
不关心是否产生拷贝
if ( NULL
== jniPrimitiveByteArray )
{
__android_log_print(
ANDROID_LOG_INFO,
"jstring2pchar",
"Call
GetByteArrayElements to get array pointer failed!"
);
iResult = -7;
break;
}
if ( ( NULL != pcOutputString
) &&
( jniByteArraySize
> *puiOutputStringLen ) )
{
__android_log_print(
ANDROID_LOG_INFO,
"jstring2pchar",
"pcOutputString is less than need!"
);
iResult = -8;
break;
}
if ( NULL != pcOutputString
)
{
memset( pcOutputString, 0, *puiOutputStringLen
);
memcpy( pcOutputString, jniPrimitiveByteArray,
jniByteArraySize );
}
// 返回转换后的字节个数(不含‘\0’) -
四字节内容覆盖
*puiOutputStringLen =
jniByteArraySize;
break; //
正常流程到此结束
} while
( 0 );
if (
NULL != jniPrimitiveByteArray )
{
// 与 GetByteArrayElements
函数对应,释放其返回值指向的数组
(*env)->ReleaseByteArrayElements(
env,
jniByteArray,
jniPrimitiveByteArray,
0 ); // 复制回内容并释放 参数三 的缓冲区
jniPrimitiveByteArray =
NULL;
}
return
iResult;
}
//
指定编码且以零('\0')结束的 char 数组转为 Java String
jstring
pchar2jstring( IN JNIEnv*
env,
IN
const char* pcInputString,
OUT const
char* pcEncoding )
{
// 待返回的
Java String
jstring
jniReturnString = NULL;
// Java
字符串的类和获取字节的方法ID
jclass
jniStringClass =
NULL;
jmethodID jniInitMethodID = NULL;
//
指定转换字符串时用的编码格式
jstring
jniEncoding = NULL;
// 取得
字符串 转换成 字节数组
jbyteArray jniByteArray = NULL;
do //
非循环,只是为了减少分支缩进
{
// 要转换的字符串或要传出字节个数的变量指针为 NULL
时
if ( ( NULL == env )
||
( NULL == pcInputString ) ||
( '\0' == *pcInputString )
)
{
__android_log_print(
ANDROID_LOG_INFO,
"pchar2jstring",
"Parameter
is invalid!" );
break;
}
// 指定字符串编码格式
if ( NULL
== pcEncoding )
{
jniEncoding =
(*env)->NewStringUTF( env, "utf-8"
);
}
else
{
jniEncoding
=(*env)->NewStringUTF( env, pcEncoding
);
}
if ( NULL == jniEncoding
)
{
__android_log_print(
ANDROID_LOG_INFO,
"jstring2pchar",
"Call
NewStringUTF to get specific encoding failed!" );
break;
}
// 获取 Java String 类和回调方法 I
D信息,
//
也可以用全局变量记下来,免得浪费时间重复执行。
jniStringClass =
(*env)->FindClass( env,
"java/lang/String"
);
if ( NULL == jniStringClass
)
{
__android_log_print(
ANDROID_LOG_INFO,
"jstring2pchar",
"Call
FindClass to get java/lang/String failed!" );
break;
}
jniInitMethodID =
(*env)->GetMethodID( env,
jniStringClass,
"",
"([BLjava/lang/String;)V" );
if ( NULL == jniInitMethodID
)
{
__android_log_print(
ANDROID_LOG_INFO,
"jstring2pchar",
"Call
GetMethodID to get failed!" );
break;
}
// 新建一个字节数组
jniByteArray =
(*env)->NewByteArray( env, strlen( pcInputString )
);
//
将基本类型数组中的某一区域从缓冲区中复制过来
(*env)->SetByteArrayRegion( env,
jniByteArray,
// Java 数组
0,
//
起始下标
strlen( pcInputString ), //
要复制的元素个数
(jbyte*)pcInputString ); //
来源缓冲区
// 用新建的字节数组来构建 Java
String
jniReturnString =
(jstring)(*env)->NewObject( env,
jniStringClass,
jniInitMethodID,
jniByteArray,
jniEncoding );
} while
( 0 );
return
jniReturnString;
}
加载中,请稍候......