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");
		}
	}
}

执行:

 

posted @ 2018-03-07 18:03  半生戎马,共话桑麻、  阅读(362)  评论(0)    收藏  举报
levels of contents