NDK开发 从入门到放弃(三:类型对应、字符串的操作、类型签名)
2016-10-31 11:55
288 查看
前言
我们之前的例子都是没有从Java代码中传参数给C++函数的,但是实际使用中大都是需要进行不同类型的数据传参与获取的,这就涉及到Java和C++的类型对应转换。主要涉及以下几点:java方法里面将参数传入本地方法;
在本地方法里面创建java对象;
在本地方法里面return结果给java程序。
数据类型对应
从Java程序中传到本地方法中的原始类型可以直接使用,对应关系表如下所示:Java 类型 | 本地类型 | 描述 |
---|---|---|
boolean | jboolean | C/C++8位整型 |
byte | jbyte | C/C++带符号的8位整型 |
char | jchar | C/C++无符号的16位整型 |
short | jshort | C/C++带符号的16位整型 |
int | jint | C/C++带符号的32位整型 |
long | jlong | C/C++带符号的64位整型e |
float | jfloat | C/C++32位浮点型 |
double | jdouble | C/C++64位浮点型 |
void | void | N/A |
Object | jobject | 任何Java对象,或者没有对应java类型的对象 |
Class | jclass | Class对象 |
String | jstring | 字符串对象 |
Object[] | jobjectArray | 任何对象的数组 |
boolean[] | jbooleanArray | 布尔型数组 |
byte[] | jbyteArray | 比特型数组 |
char[] | jcharArray | 字符型数组 |
short[] | jshortArray | 短整型数组 |
int[] | jintArray | 整型数组 |
long[] | jlongArray | 长整型数组 |
float[] | jfloatArray | 浮点型数组 |
double[] | jdoubleArray | 双浮点型数组 |
JNI字符串函数
常用的JNI函数将在后续介绍,这里给出其中的字符串操作函数的函数名以及相关描述。JNI函数 | 描述 |
---|---|
GetStringChars ReleaseStringChars | 获得/释放一个Unicode格式的字符串指针,可能返回一个字符串的副本 |
GetStringUTFChars ReleaseStringUTFChars | 获得/释放一个UTF-8格式的字符串指针,可能返回一个字符串的副本 |
GetStringLength | 返回Unicode格式字符串的长度 |
GetStringUTFLength | 返回UTF-8格式字符串的长度 |
NewString | 根据Unicode格式的C字符串创建一个Java字符串 |
NewStringUTF | 根据UTF-8格式的C字符串创建一个Java字符串 |
GetStringCritical ReleaseStringCritical | 获得/释放一个Unicode格式的字符串指针,可能返回一个字符串的副本【在该函数对区间内,不能使用任何JNI函数】 |
GetStringRegion | 将Unicode格式的String复制到预分配的缓冲区中 |
GetStringUTFRegion | 将UTF-8格式的String复制到预分配的缓冲区中 |
类型签名
类型签名 | Java 类型 |
---|---|
Z | boolean |
B | byte |
C | char |
S | short |
I | int |
J | long |
F | float |
D | double |
V | void |
L | fully-qualified-class ; 全限定的类 |
[ type | type[] |
( arg-types ) ret-type | 方法类型 |
L签名较为特殊,在类的全称前面加
L,后面还要加上
;。写参数类型签名时,类型之间没有空格没有
,分隔符。
例如,Java方法:
boolean func(int n, String s, int[] arr);
具有以下类型签名:
(ILjava/lang/String;[I)Z
简单实例
我们用一个简单的动态注册JNI的例子来演示参数传递与字符串处理,从java函数中传递两个int型数据给C++函数,进行加法计算,然后在字符串中返回计算结果。public class JNIDynamicUtils{ /** * 调用C++代码的方法,计算两数相加的结果返回对应的字符串 * @return */ public static native String getSumFromJNI(int i1, int i2); /** * 加载so库或jni库 */ static { System.loadLibrary("JNI_DYNAMIC_ANDROID_TEST"); } }
#include <stdio.h> #include <jni.h> #include <stdlib.h> jstring calcSum(JNIEnv *env, jclass clazz, jint i1, jint i2) { char result[50]; sprintf(result, " this is string from jni. result is %d", (i1 + i2)); return env->NewStringUTF(result); } /** * JNINativeMethod由三部分组成: * (1)Java中的函数名; * (2)函数签名,格式为(输入参数类型)返回值类型; * ()Ljava/lang/String; (II)表示需要传两个int型参数,Ljava/lang/String;表示返回String,在对象类名(包括包名,‘/’间隔)前面加L,分号结尾 * (3)native函数名 */ static JNINativeMethod gMethods[] = { {"getSumFromJNI", "(II)Ljava/lang/String;", (void *)calcSum }}; //System.loadLibrary过程中会自动调用JNI_OnLoad,在此进行动态注册 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) { JNIEnv *env = NULL; jint result = JNI_FALSE; //获取env指针 if (jvm->GetEnv((void**) &env, JNI_VERSION_1_6) != JNI_OK) { return result; } if (env == NULL) { return result; } //获取类引用 jclass clazz = env->FindClass("com/xiaoyu/android/tools/JNIDynamicUtils"); if (clazz == NULL) { return result; } //注册方法 if (env->RegisterNatives(clazz, gMethods, sizeof(gMethods) / sizeof(gMethods[0])) < 0) { return result; } //成功 result = JNI_VERSION_1_6; return result; }
int sprintf( char *buffer, const char *format, [ argument] … );
类似于printf,根据格式化字符串format,将后续参数列表中的参数逐个输出。不过输出目标不是标准输出终端,而是字符串buffer。
点击按钮时调用以下方法(tips:本打算用静态注册jni,后来为了用到类型签名,换成了动态注册。请忽略下面的
string from static jni的错误。):
tvInfo.setText("--->string from static jni: " + JNIDynamicUtils.getSumFromJNI(3, 4));
相关文章推荐
- NDK开发之字符串操作
- NDK开发 从入门到放弃(二:动态注册JNI、多JNI调用)
- MySQL从入门到放弃第二章:数据类型与操作数据表
- NDK开发之字符串操作
- 4、Redis从入门到放弃 之 常用命令和基本数据类型操作
- JNI&NDK开发从入门到放弃(一)
- NDK开发 从入门到放弃(七:Android Studio 2.2 CMAKE 高效NDK开发)
- Android Studio NDK 入门教程(3)--Java与C++之间的类型签名
- NDK开发 从入门到放弃(一:基本流程入门了解)
- NDK开发 从入门到放弃(五:JNI抛异常)
- Android NDK开发之 NDK类型签名
- NDK开发 从入门到放弃(一:基本流程入门了解)
- 【Go入门教程4】变量(var),常量(const),内置基础类型(Boolean、数值 byte,int,rune、字符串、错误类型),分组,iota枚举,array(数值),slice(切片),map(字典),make/new操作,零值
- NDK开发 从入门到放弃(七:Android Studio 2.2 CMAKE 高效NDK开发)
- Redis从入门到放弃 之 常用命令和基本数据类型操作
- NDK开发 从入门到放弃(七:Android Studio 2.2 CMAKE 高效NDK开发)
- NDK开发 从入门到放弃(七:Android Studio 2.2 CMAKE 高效NDK开发)
- NDK开发 从入门到放弃(六:JAVA与C++灰化图片的效率对比)
- NDK开发 从入门到放弃(四:JNI函数、C与C++调用函数的区别)
- NDK开发之字符串操作