Java调用本地C++方法【进阶:可简单调用各种类型的方法,无参,各种形参,无返回值,各种返回值】
一、无参无返回值
Java代码:
package com.lvshitech.javaandc; public class MainCls { // 无参无返回值 public native void sayHello(); }
C++:(如果不会编写这个C++程序,就使用Java语言编写,然后自动编译生成这个.h文件再拷贝进来,具体操作方法见:http://www.cnblogs.com/josephcnblog/articles/7771848.html)
#include <iostream> #include "com_lvshitech_javaandc_MainCls.h" #include <jawt_md.h> #include <jni.h> #include <jni_md.h> using namespace std; // 无参无返回值的C++本地方法 JNIEXPORT void JNICALL Java_com_lvshitech_javaandc_MainCls_sayHello(JNIEnv *env, jobject obj) { cout << "Java调用无参无返回值的C++本地方法" << endl; }
Java测试代码:
package com.lvshitech.javaandc; public class MainCls { // 无参无返回值 public native void sayHello(); // 测试 public static void main(String[] args) { // 加载本地动态库 System.loadLibrary("JavaAndC"); // 创建MainCls类对象 MainCls mainCls = new MainCls(); // 调用本地C++动态库方法 mainCls.sayHello(); } }
执行:
二、无返回值有简单形参
(1)int 类型
Java代码:
package com.lvshitech.javaandc; public class MainCls { // int类型的参数无返回值 public native void sayHello(int num); }
C++代码:
#include <iostream> #include "com_lvshitech_javaandc_MainCls.h" #include <jawt_md.h> #include <jni.h> #include <jni_md.h> using namespace std; // 无参无返回值的C++本地方法 JNIEXPORT void JNICALL Java_com_lvshitech_javaandc_MainCls_sayHello(JNIEnv *env, jobject obj, jint num) { cout << "Java调用int类型的参数无返回值的C++本地方法:num = " << num << endl; }
Java测试代码:
package com.lvshitech.javaandc; public class MainCls { // int类型的参数无返回值 public native void sayHello(int num); // 测试 public static void main(String[] args) { // 加载本地动态库 System.loadLibrary("JavaAndC"); // 创建MainCls类对象 MainCls mainCls = new MainCls(); // 调用本地C++动态库方法 mainCls.sayHello(100); } }
执行:
(2)int[] 数组类型
Java代码:
package com.lvshitech.javaandc; public class MainCls { // int[]数组类型的参数无返回值 public native void sayHello(int ... num); }
C++代码:
#include <iostream> #include <string> #include "com_lvshitech_javaandc_MainCls.h" #include <jawt_md.h> #include <jni.h> #include <jni_md.h> using namespace std; // 无参无返回值的C++本地方法 /* JNIEnv *env,代表了 Java 虚拟机 Java VM,代表了 Java 的环境,通过指针 *env 可以对 Java 端代码进行操作,是Java和本地语言(比如C++)通信的桥梁, 例如,创建Java类中的对象,调用Java对象的方法,获取Java对象中的属性等等, JNIEnv 的指针会被 JNI 传入到本地方法的实现函数中来对Java端的代码进行操作。查看 JNIEnv 可以看到各种各样的方法 */ JNIEXPORT void JNICALL Java_com_lvshitech_javaandc_MainCls_sayHello(JNIEnv *env, jobject obj, jintArray dat) { cout << "Java调用int[]数组类型的参数无返回值的C++本地方法:" << endl; // 声明数组指针 jint *arr; // 本地类型的jint对应java类型的int,其他类型请查看数据类型映射表 arr = (env)->GetIntArrayElements(dat, false); // 从虚拟机的环境变量env中获取传递过来的数组dat并赋值给数组指针 if (!arr) { cout << "数组为空!" << endl; } else { // 遍历数组 for (int i = 0; i < 5; i++) { cout << i + 1 << " : " << arr[i] << endl; } } // 释放资源 (env)->ReleaseIntArrayElements(dat, arr, 0); }
Java测试代码:
package com.lvshitech.javaandc; public class MainCls { // int[]数组类型的参数无返回值 public native void sayHello(int ... num); // 测试 public static void main(String[] args) { // 加载本地动态库 System.loadLibrary("JavaAndC"); // 创建MainCls类对象 MainCls mainCls = new MainCls(); // 调用本地C++动态库方法 int num[] = {10, 11, 12, 13, 14}; mainCls.sayHello(num); } }
执行:
改变数组大小:int num[] = {10, 11, 12, 13, 14, 15, 16};
输出和上面一样,减少数组大小:int num[] = {10, 11, 12};
输出:
(3)返回 int,无形参
Java代码:
package com.lvshitech.javaandc; public class MainCls { // 返回 int,无形参 public native int sayHello(); }
C++代码:
#include <iostream> #include "com_lvshitech_javaandc_MainCls.h" #include <jawt_md.h> #include <jni.h> #include <jni_md.h> using namespace std; // 返回 int,无形参(JNIEnv *env, jobject obj,是Java环境自带的形参,这里说的是用户自己传入的形参) JNIEXPORT jint JNICALL Java_com_lvshitech_javaandc_MainCls_sayHello(JNIEnv *env, jobject obj) { return 100; }
Java测试代码:
package com.lvshitech.javaandc; public class MainCls { // 返回 int,无形参 public native int sayHello(); // 测试 public static void main(String[] args) { // 加载本地动态库 System.loadLibrary("JavaAndC"); // 创建MainCls类对象 MainCls mainCls = new MainCls(); // 调用本地C++动态库方法 int ret = mainCls.sayHello(); System.out.println("调用C++本地方法返回的值:" + ret); } }
执行:
(4)有返回值(int[]),有形参(int[])
Java代码:
package com.lvshitech.javac; public class MainCls { public native int[] sayHello(int ... inArr); }
C++代码:
#include <iostream> // 导入有关JNI的库文件以及Java函数生成的本地.h文件 #include "com_lvshitech_javac_MainCls.h" #include <jawt_md.h> #include <jni.h> #include <jni_md.h> using namespace std; /* inArr:Java传入的int类型的数组 返回:jintArray,int类型的数组 实现数组元素 +10 的操作 */ JNIEXPORT jintArray JNICALL Java_com_lvshitech_javac_MainCls_sayHello (JNIEnv *env, jobject obj, jintArray inArr) { // 获取传入的数组大小 jsize inArrLen = env->GetArrayLength(inArr); // 如果数组为空数组,则直接结束 if (inArrLen == 0) { return NULL; } // 声明一个jint*类型的指针变量,用以接收传入的数组,遍历数组+10操作 jint* tmp = env->GetIntArrayElements(inArr, false); for (int i = 0; i < inArrLen; i++) { tmp[i] += 10; } // 创建一个jintArray的空数组,用以接收+10后的新数组元素 jintArray retArr = env->NewIntArray(inArrLen); // 接收新数组元素,SetIntArrayRegion(空数组,数组起始下标,数组大小,新数组指针变量) env->SetIntArrayRegion(retArr, 0, inArrLen, tmp); // 释放资源 env->ReleaseIntArrayElements(inArr, tmp, 0); // 返回数组 return retArr; }
测试代码:
package com.lvshitech.javac; public class MainCls { public native int[] sayHello(int ... inArr); public static void main(String[] args) { System.loadLibrary("demo"); MainCls mcls = new MainCls(); int[] inArr = {-14, 2, 34, 5, 1, 89}; int[] retArr = mcls.sayHello(inArr); if(retArr != null && retArr.length > 0) { for (int i=0; i<retArr.length; i++) { System.out.println((i+1) + " : " + retArr[i]); } } else { System.out.println("JNI返回的数组长度为0"); } } }
执行: