4个案例速学JNI(Java 代码调用 C 函数,附完整项目)

本文通过三个实例深入解析了Java Native Interface (JNI) 的使用,包括Java调用C函数进行基本运算、字符串处理及数组操作。同时,提供了一个检查密码的小应用,展示了跨语言调用的具体实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

整个Demo下载

链接:https://github.com/linweimao/NDK-Java-C-

建议先看上篇文章

https://blog.csdn.net/weixin_42814000/article/details/105279905

生成头文件的方式

点击 Terminal 输入命令,便可以生成一个JNI的 C 头文件.

输入第二个命令行提示错误的原因是注释为中文。所以在输入命令行时不能出现注释或者中文
在这里插入图片描述

javac  -h  ./  JNI.java

上面的命令的作用:根据Java中的 native 方法生成对应在 C 中的方法该怎么写(自动生成)

这样为正确的,输入命令行没问题
在这里插入图片描述
这样会提示错误
在这里插入图片描述
下图为生成的头文件
在这里插入图片描述
JNI的头文件的代码如下
在这里插入图片描述

Java 调用 C 函数执行加法运算

测试1: 将传入的两个int值相加并返回
  1. 测试目标: int值运算
  2. Java端代码
    public native int sum(int x, int y);
  3. C端代码
JNIEXPORT jint JNICALL Java_com_atguigu_javacallc_JNIS_sum

  (JNIEnv * env, jobject obj, jint x, jint y) {


	//jint可以直接进行算术运算
	int sum = x+y;

	printf("printf c sum=%d\n", sum);//问题: 直接输出在eclipse的logcat中看不到输出

	//可直接将int类型数据作为jint返回
	return sum;
}

Java 调用 C 函数执行字符串运算

测试2: 将两个字符串拼接后返回
  1. 测试目标: 字符串操作

  2. Java端代码

public native String sayHello(String s);
  1. C端代码(用到的函数 strcat )
/**
 * 工具函数
 * 把一个jstring转换成一个c语言的char* 类型.
 */

char* _JString2CStr(JNIEnv* env, jstring jstr) {

	 char* rtn;

	 jclass clsstring = (*env)->FindClass(env, "java/lang/String");

	 jstring strencode = (*env)->NewStringUTF(env,"GB2312");

	 jmethodID mid = (*env)->GetMethodID(env, clsstring, "getBytes", "(Ljava/lang/String;)[B");

	 jbyteArray barr = (jbyteArray)(*env)->CallObjectMethod(env, jstr, mid, strencode); // String .getByte("GB2312");

	 jsize alen = (*env)->GetArrayLength(env, barr);

	 jbyte* ba = (*env)->GetByteArrayElements(env, barr, JNI_FALSE);

	 if(alen > 0) {

		rtn = (char*)malloc(alen+1); //"\0"

		memcpy(rtn, ba, alen);

		rtn[alen]=0;

	 }

	 (*env)->ReleaseByteArrayElements(env, barr, ba,0);

	 return rtn;

}

/**

 * 字符串操作: 将两个字符串拼接后返回

//1. 将jstring类型的js转换为char*类型数据

//2. 指定另一部分字符串

//3. 将拼接两个char*类型字符串拼接在第一个上

	//string.h---char* strcat(char *, const char *);

//4. 将结果转换为jstring类型返回

	//jstring (*NewStringUTF)(JNIEnv*, const char*)

 */

JNIEXPORT jstring JNICALL Java_com_atguigu_javacallc_JNIS_sayHello

  (JNIEnv * env, jobject obj, jstring js) {

	//1. 将jstring类型的js转换为char*类型数据
	char* cs1 = _JString2CStr(env, js);

	//2. 指定另一部分字符串
	char* cs2 = " Hello By C";

	//3. 将拼接两个char*类型字符串拼接在第一个上
	char* cs3 = strcat(cs1, cs2);

	//4. 将结果转换为jstring类型返回
	return (*env)->NewStringUTF(env, cs3);
}

Java 调用 C 函数执行数组运算

测试3:将数组中的每个元素增加10
  1. 测试目标: 数组运算
  2. Java端代码
public native int[] increaseArrayEles(int[] intArray);
  1. C端代码
/**
 * 数组运算: 将数组中的每个元素增加10

//1. 得到数组的长度
	//jsize (*GetArrayLength)(JNIEnv*, jarray);

//2. 得到数组
	//jint* (*GetIntArrayElements)(JNIEnv*, jintArray, jboolean*);

//3. 遍历数组, 并将每个元素+10

//4. 返回数组

 */
JNIEXPORT jintArray JNICALL Java_com_atguigu_javacallc_JNIS_increaseArrayEles

  (JNIEnv * env, jobject obj, jintArray arr) {

	//1. 得到数组的长度
	//jsize       (*GetArrayLength)(JNIEnv*, jarray);
	jsize length = (*env)->GetArrayLength(env, arr);

	//2. 得到数组
	//jint*       (*GetIntArrayElements)(JNIEnv*, jintArray, jboolean*);
	jint* array = (*env)->GetIntArrayElements(env, arr, JNI_FALSE);

	//3. 遍历数组, 并将每个元素+10
	int i;
	for(i=0;i<length;i++) {
		*(array+i) += 10;
	}

	//4. 返回数组
	return arr;
}

检查密码是否正确

小应用: 检查密码是否正确, 如果正确返回200, 否则返回400
  1. Java端代码
/*

 * 应用: 检查密码是否正确, 如果正确返回200, 否则返回400

		"123456"

 */

public native int checkPwd(String pwd);
  1. C端代码(用到的函数 strcmp)
/**
 * 小应用: 检查密码是否正确

//1. 将jString转换为char*

//2. 比较两个字符串是否相等

	//string.h---int strcmp(const char *, const char *)

//3. 根据比较的结果返回不同的值
 */

JNIEXPORT jint JNICALL Java_com_atguigu_javacallc_JNIS_checkPwd

  (JNIEnv * env, jobject obj, jstring js) {

   //1. 将jString转换为char*
	char* cs = _JString2CStr(env, js);
	char* pwd = "123456";

	//2. 比较两个字符串是否相等
	int result = strcmp(cs, pwd);

	//3. 根据比较的结果返回不同的值
	if(result==0) {
		return 200;
	}
	return 400;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值