您的位置:首页 > 移动开发 > Android开发

Android ndk jni中回调java的方法&字段描述符

2016-09-26 09:41 176 查看

一、jobject和jclass

1.如果定义native方法时使用了static关键字,那么生成的头文件里就会传入jclass,代表这个类的引用。
2.如果没有使用static关键字,那么就会传入jobject,代表类的对象的引用。


二、jni回调java

先贴代码

1.java

package com.example.testcallback;

import android.util.Log;

public class TestCallbackManager {
private final String TAG = "TestCallbackManager";

static {
System.loadLibrary("TestCallback");
}

public native void start();

public void myCallback(int a) {
Log.e(TAG, "Callback: " + a);
}

}


2.生成的头文件

ps:如果native方法定义成static,这里就不是jobject,而是jclass

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_testcallback_TestCallbackManager */

#ifndef _Included_com_example_testcallback_TestCallbackManager
#define _Included_com_example_testcallback_TestCallbackManager
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class:     com_example_testcallback_TestCallbackManager
* Method:    start
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_example_testcallback_TestCallbackManager_start
(JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif


3.c文件

#include <jni.h>
#include <android/log.h>
#include "com_example_testcallback_TestCallbackManager.h"

#define TAG "TestCallbackJNI"
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)

JNIEXPORT void JNICALL Java_com_example_testcallback_TestCallbackManager_start
(JNIEnv *env, jobject obj) {
__android_log_print(ANDROID_LOG_ERROR, "Callback JNI", "begin");

jclass clazz = (*env)->GetObjectClass(env, obj);
jmethodID mID = (*env)->GetMethodID(env, clazz, "myCallback", "(I)V");
(*env)->CallVoidMethod(env, obj, mID, 10);

__android_log_print(ANDROID_LOG_ERROR, "Callback JNI", "end");
}


4.解释c文件

(1)在同一个类中,定义native方法和要调用的callback方法,为的是可以在当前的对象引用obj中找到当前类的引用,然后找到这个回调方法。

(2)GetObjectClass,通过obj找到当前类。

(3)GetMethodID找到回调方法,参数:env引用,类引用,方法名,字段描述符(这里看第四条)

(4)字段描述符:

  (a)JNI中描述字段使用字段描述符,描述方法同样有方法描述符。一个方法描述符包含参数类型和返回值类型。参数类型出现在前面,并由一对圆括号将它们括起来,参数类型按它们在方法声明中出现的顺序被列出来,并且多个参数类型之间没有分隔符。如果一个方法没有参数,被表示为一对空圆括号。方法的返回值类型紧跟参数类型的右括号后面。

  (b)描述符对应符号:

   Boolean~~~Z

   Byte~~~B

   Char~~~C

   Short~~~S

   Int~~~I

   Long~~~J

   Float~~~F

   Double~~~D

   Void~~~V

   

   objects对象:

   以”L”开头,以”;”结尾,中间是用”/” 隔开的包及类名。比如:Ljava/lang/String;。嵌套类:Ljava/xx/外部类名$内部类名;

  (c)方法描述符中可能会包含类描述符,如方法native private String getLine(String);的描述符为:“(Ljava/lang/String;)Ljava/lang/String;”

  (d)数组类型的描述符以“[”开头,后面跟着数组元素类型的描述符。如,public static void main(String[] args);的描述符是:”([Ljava/lang/String;)V”

  (e)举例:

// 描述符:(IFDZ)V
public void method1(int a,float f,double b,boolean b){
}

// 描述符:(Ljava/lang/String;)I
public int method2(String s){
return 0;
}

//描述符:()[I
public int[] method3(){
return null;
}


(5)CallVoidMethod 调用回调方法,并传入相应值。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐