JNI-Java和C之间通信


主要通过一些方法、函数来介绍下Java和C之间通信

Java通过JNI调用C函数实例代码

char*   Jstring2CStr(JNIEnv*   env,   jstring   jstr)
{
	 char*   rtn   =   NULL;
	 //c调用java中的类的方法
	 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;
}
/**
 * env代表的是   虚拟机C语言实现的结构体指针
 * obj代表的是   当前调用的对象
 * */
JNIEXPORT jint JNICALL Java_com_justsy_ndkpassdata_PassDataToC_add
  (JNIEnv * env, jobject obj, jint x, jint y)
{
	//java中int类型和c中的int类型占用的内存空间一样,可以直接返回
	return x+y;
}

//传递String类型的参数
JNIEXPORT jstring JNICALL Java_com_justsy_ndkpassdata_PassDataToC_sendMsgToC
  (JNIEnv * env, jobject obj, jstring jstr)
{
	//jstring转化为c的Char *类型
	char* cstr = Jstring2CStr(env,jstr);
	LOGD("c char %s",cstr);
	char marr[7] = {' ','h','e','l','l','o','\0'};//\0结束
	strcat(cstr,marr);//拷贝
	LOGD("c char add arr is %s",cstr);
	return (*env)->NewStringUTF(env,cstr);
}

//传递int数组
JNIEXPORT jintArray JNICALL Java_com_justsy_ndkpassdata_PassDataToC_sendArrayToC
  (JNIEnv * env, jobject obj, jintArray carr)
{
	//arr length
	int arrLen = (*env)->GetArrayLength(env,carr);

	//返回的是array的首地址
	jint* intarr = (*env)->GetIntArrayElements(env,carr,0);

	int i = 0;
	for(;i<arrLen;i++)
	{
		*(intarr+i) += 10;
	}

	return carr;
}

/**
 * java静态方法对应的c函数
 * jclass代表的是调用的类
 * */
JNIEXPORT jint JNICALL Java_com_justsy_ndkpassdata_PassDataToC_sub
  (JNIEnv * env, jclass clazz, jint x, jint y)
{
	return x-y;
}

对应的Java native方法为

	public native String sendMsgToC(String msg);
	
	public native int[] sendArrayToC(int[] arr);
	
	public native static int sub(int x,int y);

C通过JNI调用Java方法实例代码

/*
 * Class:     tu_bb_ndk_DataProvider
 * Method:    callmethod1
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_tu_bb_ndk_DataProvider_callmethod1
  (JNIEnv * env, jobject obj)
{

	//获取jclass,对应java类的class对象
	jclass clazz = (*env)->FindClass(env, "tu/bb/ndk/DataProvider");

	if(clazz==0)
	{
		LOGD("clazz can't get");
		return;
	}

	//获取方法ID,提供jclass、方法名和方法签名,方法签名可以jdk提供的javap -s 类全名 命令得到
	jmethodID method1ID = (*env)->GetMethodID(env, clazz, "sayHelleFromC", "()V");

	if(method1ID==0)
	{
		LOGD("method1ID can't get");
		return;
	}

	//调用无参方法
	(*env)->CallVoidMethod(env, obj, method1ID);
}

/*
 * Class:     tu_bb_ndk_DataProvider
 * Method:    callmethod2
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_tu_bb_ndk_DataProvider_callmethod2
  (JNIEnv * env, jobject obj)
{
	jclass clazz = (*env)->FindClass(env, "tu/bb/ndk/DataProvider");

	if(clazz==0)
	{
		LOGD("clazz can't get");
		return;
	}

	jmethodID method2ID = (*env)->GetMethodID(env, clazz, "add", "(II)I");

	if(method2ID==0)
	{
		LOGD("method2ID can't get");
	}

	//调用有参方法,(*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...),可变参数
	jint result = (*env)->CallIntMethod(env, obj, method2ID, 1,2);

	LOGD("result %d",result);
}

/*
 * Class:     tu_bb_ndk_DataProvider
 * Method:    callmethod3
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_tu_bb_ndk_DataProvider_callmethod3
  (JNIEnv * env, jobject obj)
{
	jclass clazz = (*env)->FindClass(env, "tu/bb/ndk/DataProvider");

	if(clazz==0)
	{
		LOGD("clazz can't get");
		return;
	}

	jmethodID method3ID = (*env)->GetMethodID(env, clazz, "getMsgFromC", "(Ljava/lang/String;)V");

	if(method3ID==0)
	{
		LOGD("method3ID can't get");
		return;
	}

	(*env)->CallVoidMethod(env, obj, method3ID, (*env)->NewStringUTF(env,"HelloWorld"));

}

JNIEXPORT void JNICALL Java_tu_bb_ndk_DataProvider_callmethod4
  (JNIEnv * env, jobject obj)
{
	jclass clazz = (*env)->FindClass(env, "tu/bb/ndk/DataProvider");

	if(clazz==0)
	{
		LOGD("clazz can't get");
		return;
	}

	jmethodID  method4ID =  (*env)->GetStaticMethodID(env, clazz, "getStaticMsgFromC", "(Ljava/lang/String;)V");

	if(method4ID==0)
	{
		LOGD("method4ID can't get");
		return;
	}

	//调用静态的Java方法,第二个参数改为jclass对象,这里还是很好理解的
	(*env)->CallStaticVoidMethod(env, clazz, method4ID, (*env)->NewStringUTF(env,"static hello"));
}

对应的Java native方法

	public void sayHelleFromC(){
		System.out.println("Hello World");
	} 
	
	public int add(int x,int y){
		return x+y;
	}
	
	public void getMsgFromC(String msg){
		System.out.println("msg:"+msg);
	}
	
	public static void getStaticMsgFromC(String msg){
		System.out.println("msg:"+msg);
	}
	
	public native void callmethod1();
	public native void callmethod2();
	public native void callmethod3();
	public native void callmethod4();

注:所有的java和c数据类型之间的转换均可参考jni.h头文件中的定义,jni.h位于android-ndk-r7b\platforms\android-9\arch-arm\usr\include下



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值