介绍Java如何将数据传递给C和C回调Java的方法。 java传递数据给C,在C代码中进行处理数据,处理完数据后返回给java。C的回调是Java传递数据给C,C需要用到Java中的某个方法,就需要调用java的方法。

Android中使用JNI七个步骤:

1.创建一个android工程

2.JAVA代码中写声明native 方法 public native String helloFromJNI();

3.用javah工具生成头文件

4. 创建jni目录,引入头文件,根据头文件实现c代码

5.编写Android.mk文件

6.Ndk编译生成动态库

7.Java代码load 动态库.调用native代码

Java调用C进行数据传递

这里分别传递整形、字符串、数组在C中进行处理。

声明native 方法:

[java] view plaincopy
  1. publicclassDataProvider{
  2. //两个java中的int传递c语言,c语言处理这个相加的逻辑,把相加的结果返回给java
  3. publicnativeintadd(intx,inty);
  4. //把一个java中的字符串传递给c语言,c语言处理下字符串,处理完毕返回给java
  5. publicnativeStringsayHelloInC(Strings);
  6. //把一个java中int类型的数组传递给c语言,c语言里面把数组的每一个元素的值都增加5,
  7. //然后在把处理完毕的数组,返回给java
  8. publicnativeint[]intMethod(int[]iNum);
  9. }

以上方法要在C中实现的头文件,头文件可以理解为要在C中实现的方法

其中 JENEnv* 代表的是java环境 , 通过这个环境可以调用java的方法,jobject 表示哪个对象调用了 这个c语言的方法, thiz就表示的是当前的对象

[cpp] view plaincopy
  1. /*DONOTEDITTHISFILE-itismachinegenerated*/
  2. #include<jni.h>
  3. /*Headerforclasscn_itcast_ndk3_DataProvider*/
  4. #ifndef_Included_cn_itcast_ndk3_DataProvider
  5. #define_Included_cn_itcast_ndk3_DataProvider
  6. #ifdef__cplusplus
  7. extern"C"{
  8. #endif
  9. /*
  10. *Class:cn_itcast_ndk3_DataProvider
  11. *Method:add
  12. *Signature:(II)I
  13. */
  14. JNIEXPORTjintJNICALLJava_cn_itcast_ndk3_DataProvider_add
  15. (JNIEnv*,jobject,jint,jint);
  16. /*
  17. *Class:cn_itcast_ndk3_DataProvider
  18. *Method:sayHelloInC
  19. *Signature:(Ljava/lang/String;)Ljava/lang/String;
  20. */
  21. JNIEXPORTjstringJNICALLJava_cn_itcast_ndk3_DataProvider_sayHelloInC
  22. (JNIEnv*,jobject,jstring);
  23. /*
  24. *Class:cn_itcast_ndk3_DataProvider
  25. *Method:intMethod
  26. *Signature:([I)[I
  27. */
  28. JNIEXPORTjintArrayJNICALLJava_cn_itcast_ndk3_DataProvider_intMethod
  29. (JNIEnv*,jobject,jintArray);
  30. #ifdef__cplusplus
  31. }
  32. #endif
  33. #endif

C代码出了要引用头文件外,还要引入日志信息,以方便在C 中进行调试

[cpp] view plaincopy
  1. //引入头文件
  2. #include"cn_itcast_ndk3_DataProvider.h"
  3. #include<string.h>
  4. //导入日志头文件
  5. #include<android/log.h>
  6. //修改日志tag中的值
  7. #defineLOG_TAG"logfromc"
  8. //日志显示的等级
  9. #defineLOGD(...)__android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
  10. #defineLOGI(...)__android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
  11. //java中的jstring,转化为c的一个字符数组
  12. char*Jstring2CStr(JNIEnv*env,jstringjstr)
  13. {
  14. char*rtn=NULL;
  15. jclassclsstring=(*env)->FindClass(env,"java/lang/String");
  16. jstringstrencode=(*env)->NewStringUTF(env,"GB2312");
  17. jmethodIDmid=(*env)->GetMethodID(env,clsstring,"getBytes","(Ljava/lang/String;)[B");
  18. jbyteArraybarr=(jbyteArray)(*env)->CallObjectMethod(env,jstr,mid,strencode);//String.getByte("GB2312");
  19. jsizealen=(*env)->GetArrayLength(env,barr);
  20. jbyte*ba=(*env)->GetByteArrayElements(env,barr,JNI_FALSE);
  21. if(alen>0)
  22. {
  23. rtn=(char*)malloc(alen+1);//newchar[alen+1];"\0"
  24. memcpy(rtn,ba,alen);
  25. rtn[alen]=0;
  26. }
  27. (*env)->ReleaseByteArrayElements(env,barr,ba,0);//释放内存
  28. returnrtn;
  29. }
  30. //处理整形相加
  31. JNIEXPORTjintJNICALLJava_cn_itcast_ndk3_DataProvider_add
  32. (JNIEnv*env,jobjectobj,jintx,jinty){
  33. //打印java传递过来的jstring;
  34. LOGI("logfromccode");
  35. LOGI("x=%ld",x);
  36. LOGD("y=%ld",y);
  37. returnx+y;
  38. }
  39. //处理字符串追加
  40. JNIEXPORTjstringJNICALLJava_cn_itcast_ndk3_DataProvider_sayHelloInC
  41. (JNIEnv*env,jobjectobj,jstringstr){
  42. char*p=Jstring2CStr(env,str);
  43. LOGI("%s",p);
  44. char*newstr="appendstring";
  45. //strcat(dest,sorce)把sorce字符串添加到dest字符串的后面
  46. LOGI("END");
  47. return(*env)->NewStringUTF(env,strcat(p,newstr));
  48. }
  49. //处理数组中的每一个元素
  50. JNIEXPORTjintArrayJNICALLJava_cn_itcast_ndk3_DataProvider_intMethod
  51. (JNIEnv*env,jobjectobj,jintArrayarr){
  52. //1.获取到arr的大小
  53. intlen=(*env)->GetArrayLength(env,arr);
  54. LOGI("len=%d",len);
  55. if(len==0){
  56. returnarr;
  57. }
  58. //取出数组中第一个元素的内存地址
  59. jint*p=(*env)->GetIntArrayElements(env,arr,0);
  60. inti=0;
  61. for(;i<len;i++){
  62. LOGI("len=%ld",*(p+i));//取出的每个元素
  63. *(p+i)+=5;//取出的每个元素加五
  64. }
  65. returnarr;
  66. }

编写Android.mk文件

[cpp] view plaincopy
  1. LOCAL_PATH:=$(callmy-dir)
  2. include$(CLEAR_VARS)
  3. LOCAL_MODULE:=Hello
  4. LOCAL_SRC_FILES:=Hello.c
  5. #增加log函数对应的log库liblog.solibthread_db.a
  6. LOCAL_LDLIBS+=-llog
  7. include$(BUILD_SHARED_LIBRARY)

Java代码load 动态库.调用native代码

[java] view plaincopy
  1. static{
  2. System.loadLibrary("Hello");
  3. }
  4. DataProviderdp;
  5. @Override
  6. publicvoidonCreate(BundlesavedInstanceState){
  7. super.onCreate(savedInstanceState);
  8. setContentView(R.layout.main);
  9. dp=newDataProvider();
  10. }
  11. //add对应的事件
  12. publicvoidadd(Viewview){
  13. //执行C语言处理数据
  14. intresult=dp.add(3,5);
  15. Toast.makeText(this,"相加的结果"+result,1).show();
  16. }

C中回调java方法

声明native 方法:

[java] view plaincopy
  1. publicclassDataProvider{
  2. publicnativevoidcallCcode();
  3. publicnativevoidcallCcode1();
  4. publicnativevoidcallCcode2();
  5. ///C调用java中的空方法
  6. publicvoidhelloFromJava(){
  7. System.out.println("hellofromjava");
  8. }
  9. //C调用java中的带两个int参数的方法
  10. publicintAdd(intx,inty){
  11. System.out.println("相加的结果为"+(x+y));
  12. returnx+y;
  13. }
  14. //C调用java中参数为string的方法
  15. publicvoidprintString(Strings){
  16. System.out.println("injavacode"+s);
  17. }
  18. }

头文件可以用jdk自带的javah进行自动生成,使用javap -s可以获取到方法的签名。

C代码实现回调需要三个步骤:首先要要获取到 某个对象 , 然后获取对象里面的方法 ,最后 调用这个方法 .

[cpp] view plaincopy
  1. #include"cn_itcast_ndk4_DataProvider.h"
  2. #include<string.h>
  3. #include<android/log.h>
  4. #defineLOG_TAG"logfromc"
  5. #defineLOGD(...)__android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
  6. #defineLOGI(...)__android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
  7. //1.调用java中的无参helloFromJava方法
  8. JNIEXPORTvoidJNICALLJava_cn_itcast_ndk4_DataProvider_callCcode
  9. (JNIEnv*env,jobjectobj){
  10. //获取到DataProvider对象
  11. char*classname="cn/itcast/ndk4/DataProvider";
  12. jclassdpclazz=(*env)->FindClass(env,classname);
  13. if(dpclazz==0){
  14. LOGI("notfindclass!");
  15. }else
  16. LOGI("findclass");
  17. //第三个参数和第四个参数是方法的签名,第三个参数是方法名,第四个参数是根据返回值和参数生成的
  18. //获取到DataProvider要调用的方法
  19. jmethodIDmethodID=(*env)->GetMethodID(env,dpclazz,"helloFromJava","()V");
  20. if(methodID==0){
  21. LOGI("notfindmethod!");
  22. }else
  23. LOGI("findmethod");
  24. //调用这个方法
  25. (*env)->CallVoidMethod(env,obj,methodID);
  26. }
  27. //2.调用java中的printString方法传递一个字符串
  28. JNIEXPORTvoidJNICALLJava_cn_itcast_ndk4_DataProvider_callCcode1
  29. (JNIEnv*env,jobjectobj){
  30. LOGI("incode");
  31. //获取到DataProvider对象
  32. char*classname="cn/itcast/ndk4/DataProvider";
  33. jclassdpclazz=(*env)->FindClass(env,classname);
  34. if(dpclazz==0){
  35. LOGI("notfindclass!");
  36. }else
  37. LOGI("findclass");
  38. //获取到要调用的method
  39. jmethodIDmethodID=(*env)->GetMethodID(env,dpclazz,"printString","(Ljava/lang/String;)V");
  40. if(methodID==0){
  41. LOGI("notfindmethod!");
  42. }else
  43. LOGI("findmethod");
  44. //调用这个方法
  45. (*env)->CallVoidMethod(env,obj,methodID,(*env)->NewStringUTF(env,"haha"));
  46. }
  47. //3.调用java中的add方法,传递两个参数jintx,y
  48. JNIEXPORTvoidJNICALLJava_cn_itcast_ndk4_DataProvider_callCcode2
  49. (JNIEnv*env,jobjectobj){
  50. char*classname="cn/itcast/ndk4/DataProvider";
  51. jclassdpclazz=(*env)->FindClass(env,classname);
  52. jmethodIDmethodID=(*env)->GetMethodID(env,dpclazz,"Add","(II)I");
  53. (*env)->CallIntMethod(env,obj,methodID,3l,4l);
  54. }

转自:http://blog.csdn.net/furongkang/article/details/6857610

更多相关文章

  1. 浅谈Java中Collections.sort对List排序的两种方法
  2. Python list sort方法的具体使用
  3. python list.sort()根据多个关键字排序的方法实现
  4. android上一些方法的区别和用法的注意事项
  5. android实现字体闪烁动画的方法
  6. Android(安卓)Wifi模块分析(三)
  7. Android中dispatchDraw分析
  8. Android四大基本组件介绍与生命周期
  9. Android(安卓)MediaPlayer 常用方法介绍

随机推荐

  1. Default Activity not found
  2. Android(安卓)studio 3.1.2决解导入项目g
  3. Android 5.0新控件 FloatingActionButton
  4. Android之用PopupWindow实现弹出listview
  5. 今天发现的一些优秀的资源网站
  6. Simulate a key press on Android
  7. ffmpeg-2.3.3 configure for android
  8. 改变分隔条,基于数组的ListView
  9. Android 关于wifi管理的代码
  10. Android(安卓)下载一个文件以及打开这个a