• Andriod JNI编程之C++回调Java函数


    一般我们NDK编程都是Java层调用C++的接口,但其实才C++层也可以调用Java的函数。实现方法如下:

    1、获取类名:jclass cls = env->FindClass

    2、获取类方法:jmethodID mid = env->GetMethodID

    3、获取类成员变量:fieldID fid=env->GetFieldID

    4、生成类对象:jobject obj=env->NewObject (jobect也可以从Java层传下来)

    5、调用类成员方法:env->CallXXXMethod(XXX为Java方法的返回值类型)

     

    下面是一个例子:

    首先是Java的代码,首先生成一个JniTest类,里面有个sayHelloFromJava的方法,我们要实现的目标是在C++里面赋值(String str),两个整形值(int index1,  int index2),一个整形数组(int[] intArray),然后在Java里面将这些数值打印出来。

    [java] view plaincopy
    1. public class JniTest extends Activity {  
    2.     /** Called when the activity is first created. */  
    3.     @Override  
    4.     public void onCreate(Bundle savedInstanceState) {  
    5.         super.onCreate(savedInstanceState);  
    6.         setContentView(R.layout.main);  
    7.         JNI j = new JNI();  
    8.         j.write();  
    9.     }  
    10.       
    11.     public JniTest()  
    12.     {  
    13.         Log.i("TEST","JniTest Constructor");  
    14.     }  
    15.       
    16.     public int sayHelloFromJava(String str, int index1, int index2, int[] intArray)  
    17.     {  
    18.         Log.i("TEST", str + " But I am show in java");  
    19.         Log.i("TEST""index1 = " + index1 + " index2 = " + index2 );  
    20.         int javaIndex = 5;  
    21.         for(int i = 0; i < intArray.length; ++i)  
    22.         {  
    23.             Log.i("TEST""intArray[i] = " + intArray[i]);  
    24.         }  
    25.         return javaIndex;  
    26.     }  
    27. }  

     

    [java] view plaincopy
    1. public class JNI {  
    2.     static   
    3.     {  
    4.         System.loadLibrary("myjni");  
    5.     }  
    6.     public native void write();  
    7. }  

     

    然后是C++里面的代码

    1. JNIEXPORT void JNICALL Java_cc_androidos_jni_JNI_write  
    2. (JNIEnv *env, jobject j) {  
    3.     LOGI("calltest");  
    4.     jstring str = NULL;  
    5.       
    6.     jclass clz = env->FindClass("cc/androidos/jni/JniTest");  
    7.     //获取clz的构造函数并生成一个对象  
    8.     jmethodID ctor = env->GetMethodID(clz, "<init>""()V");  
    9.     jobject obj = env->NewObject(clz, ctor);  
    10.   
    11.     // 如果是数组类型,则在类型前加[,如整形数组int[] intArray,则对应类型为[I,整形数组String[] strArray对应为[Ljava/lang/String;  
    12.     jmethodID mid = env->GetMethodID(clz, "sayHelloFromJava""(Ljava/lang/String;II[I)I");  
    13.     if (mid)  
    14.     {  
    15.         LOGI("mid is get");  
    16.         jstring str1 = env->NewStringUTF("I am Native");  
    17.         jint index1 = 10;  
    18.         jint index2 = 12;  
    19.         //env->CallVoidMethod(obj, mid, str1, index1, index2);  
    20.   
    21.         // 数组类型转换 testIntArray能不能不申请内存空间  
    22.         jintArray testIntArray = env->NewIntArray(10);  
    23.         jint *test = new jint[10];  
    24.         for(int i = 0; i < 10; ++i)  
    25.         {  
    26.             *(test+i) = i + 100;  
    27.         }  
    28.         env->SetIntArrayRegion(testIntArray, 0, 10, test);  
    29.   
    30.   
    31.         jint javaIndex = env->CallIntMethod(obj, mid, str1, index1, index2, testIntArray);  
    32.         LOGI("javaIndex = %d", javaIndex);  
    33.         delete[] test;  
    34.         test = NULL;  
    35.     }  
    36. }  

    通过这个例子我们基本上就可以了解C++层是如何回调Java函数的了。另外,这里还有一个小技巧,如果你不知道你Java层的在C++中的类型是什么,你可以native方法中将这个类型写进去,然后用javah方法生成.h文件,只要查看.h文件的对应的类型注释就可以知道结果了。例如:我们想知道String、整形数组对应的类型怎么写,我们在native中加入一个public native void type(String str, int[] arrayInt)方法

    [java] view plaincopy
    1. public class JNI {  
    2.     static   
    3.     {  
    4.         System.loadLibrary("myjni");  
    5.     }  
    6.     public native void write();  
    7.     public native void type(String str, int[] arrayInt);  
    8. }  

    然后生成对应的.h文件:

    1. /* 
    2.  * Class:     cc_androidos_jni_JNI 
    3.  * Method:    type 
    4.  * Signature: (Ljava/lang/String;[I)V 
    5.  */  
    6. JNIEXPORT void JNICALL Java_cc_androidos_jni_JNI_type  
    7.   (JNIEnv *, jobject, jstring, jintArray);  

    我们注意看注释中的“Signature: (Ljava/lang/String;[I)V”,其中Ljava/lang/String;Ljava/lang/String;就是String的类型(注意分号不能丢),[I则是整形数组对应的类型。

     

  • 相关阅读:
    [python subprocess学习篇] 调用系统命令
    linux dd命令创建一定大小的文件
    [linux time命令学习篇] time 统计命令执行的时间
    新建应用母版页的网页index.aspx,about.aspx,login.aspx
    MOSS母板页制作 学习笔记(一)
    SharePoint 2010顶部链接导航栏的详细操作
    使用SharePoint 2010 母版页
    SharePoint 2010 母版页制作的简单介绍
    在 SharePoint 2010 中访问数据
    牛刀小试、用SharePoint 实现请假管理功能
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13318654.html
Copyright © 2020-2023  润新知