主要通过一些方法、函数来介绍下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下