java调用c/c++过程
1. 已采用ndk编译出c/c++库(c_libname.a/ c_libname so),根据c_libname.h编写对应的java类;
2. 根据native java类,编译出对应的cpp文件头;如下面例子:
a) 使用Java工具Javah可以很容易地创建它而不用手动去创建。你对Java的class文件使用javah命令,就会为你生成一个对应的C/C++头文件。
b) 设置好javah的环境变量,见2.1_3,打开控制台,输入 cd /d {android_project_path};
输入javah -classpath .\src –jni {package_name}.{java_class_name};
将生成jni头文件名为{package_name}_{java_class_name}.h 到控制台的当前显示路径下。
javac命令:javac {java_file_path}\{java_class_name}.java,编译出*.classes
javah命令:javah -classpath {android_project_path}\bin\classes -jni {package_name}.{java_class_name};
3. 根据生成的jni.h,实现相应的jni接口即可;
4. 接着就是library的编译了,将其编译为*.so动态库;
5. 最后Java中调用system.load 动态库后,并使用相应的native java类即可完成对c/c++调用。
a) 生成的jni对应的C/C++实现等,这里称之为本地文件/方法/类型;java类函数返回值和参数类型根据等价约定映射到本地C/C++类型,如表2-1所示:
注意:所有的本地方法的第一个参数都是指向JNIEnv结构的。这个结构是用来调用JNI函数的。第二个参数jclass的意义,要看方法是不是静态的(static)或者实例(Instance)的。前者,jclass代表一个类对象的引用,而后者是被调用的方法所属对象的引用。
表 2‑1 JNI类型映射
| Java类型 | 本地类型(jni) | 描述 |
| 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位浮点型 |
| 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 | 双浮点型数组 |
b) JNI通过JNIEnv提供的操作Java数组的功能。它提供了两个函数:一个是操作java的简单型数组的,另一个是操作对象类型数组的。
b1.简单类型的数组,使用GetXXXArrayElements函数(见表2-2),XXX代表了数组的类型;
表 2‑2 JNI数组存取函数
| 函数 | Java数组类型 | 本地类型 |
| GetBooleanArrayElements | jbooleanArray | jboolean |
| GetByteArrayElements | jbyteArray | jbyte |
| GetCharArrayElements | jcharArray | jchar |
| GetShortArrayElements | jshortArray | jshort |
| GetIntArrayElements | jintArray | jint |
| GetLongArrayElements | jlongArray | jlong |
| GetFloatArrayElements | jfloatArray | jfloat |
| GetDoubleArrayElements | jdoubleArray | jdouble |
b2.操作对象类型,JNI通过ID识别域和方法,一个域或方法的ID是任何处理域和方法的函数的必须参数。
表2-3列出了用以得到静态(static)和实例(instance)的域与方法的JNI函数。每个函数接受(作为参数)域或方法的类,它们的名称,符号和它们对应返回的jfieldID或jmethodID。
表 2‑3 域和方法的函数
| 函数 | 描述 |
| GetFieldID | 得到一个实例的域的ID |
| GetStaticFieldID | 得到一个静态的域的ID |
| GetMethodID | 得到一个实例的方法的ID |
| GetStaticMethodID | 得到一个静态方法的ID |
如果你有了一个类的实例,它就可以通过方法GetObjectClass得到,或者如果你没有这个类的实例,可以通过FindClass得到。符号是从域的类型或者方法的参数,返回值得到字符串,如表2-4所示。
表 2‑4 确定域和方法的符号
| Java 类型 | 符号 |
| boolean | Z |
| byte | B |
| char | C |
| short | S |
| int | I |
| long | L |
| float | F |
| double | D |
| void | V |
| objects对象 | Lfully-qualified-class-name;L类名 |
| Arrays数组 | [array-type [数组类型 |
| methods方法 | (argument-types)return-type(参数类型)返回类型 |
原文地址:http://blog.youkuaiyun.com/hqulyc/article/details/7857292
本文介绍如何使用Java调用C/C++库的过程,包括NDK编译C/C++库、生成JNI头文件、实现JNI接口及最终在Java中调用这些库的方法。还详细说明了Java类型与C/C++类型之间的映射关系。
4770

被折叠的 条评论
为什么被折叠?



