前言
前几天我们JNI的使用介绍过《》和《》,都是介绍Java的native方法,也就Java调用C或C++中的方法。
今天就介绍C或C++调用Java方法。记录于此,方便自己查阅。
正文
还是在之前基础上改,这里以《》代码未基础,动态注册很方便和很简单。
功能介绍:模拟计算器加减法,通过native方法传入加或减类型和数值,通过类型判读,JNI中调用Java方法进行计算,再通过native方法返回结果。
Hello.java
- package com.biumall.dynamic.one;
- public class Hello {
- //1. load Hello.so
- static {
- System.loadLibrary("Hello");
- }
- // 2. define native computer()
- public static native int computer(String type, int a, int b);
- //add
- public int add(int x, int y) {
- return x + y;
- }
- //sub
- public int sub(int x, int y) {
- return x - y;
- }
- }
Hello.c
这里依旧以C语言哈
- #include <jni.h>
- #include <android/log.h>
- #include<stdio.h>
- #include<string.h>
-
- //LOG_TAG
- #define LOG_TAG "from_dynamic_jni_+"
- #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
- #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
- #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
-
- //获取数组大小
- #define ARRAY_LENGTH(x) ((int)(sizeof(x) / sizeof((x)[0])))
- //定义Hello.java类路径[包名+类名,只不过.换成了/]
- //com.biumall.dynamic.one.Hello
- #define DYNAMIC_CLASS "com/biumall/dynamic/one/Hello"
-
- //声明方法
- int c_add(JNIEnv *env, jclass jclazz, int x, int y);
- int c_sub(JNIEnv *env, jclass jclazz, int x, int y);
-
- //native 方法
- JNIEXPORT jint JNICALL native_computer(JNIEnv *env, jclass jclazz, jstring type, jint a, jint b) {
- const char *charType = (*env)->GetStringUTFChars(env, type, 0);
- int count;
- if (!strcmp(charType, "-")) {
- count = c_sub(env, jclazz, a, b);
- } else if (!strcmp(charType, "+")) {
- count = c_add(env, jclazz, a, b);
- }
- return count;
- }
-
- //jni 调用 java add方法
- int c_add(JNIEnv *env, jclass jclazz, int x, int y) {
- jmethodID methodID = (*env)->GetMethodID(env, jclazz, "add", "(II)I");
- jobject object = (*env)->AllocObject(env, jclazz);
- return (*env)->CallIntMethod(env, object, methodID, x, y);
- }
- //jni 调用 java sub方法
- int c_sub(JNIEnv *env, jclass jclazz, int x, int y) {
- jmethodID methodID = (*env)->GetMethodID(env, jclazz, "sub", "(II)I");
- jobject object = (*env)->AllocObject(env, jclazz);
- return (*env)->CallIntMethod(env, object, methodID, x, y);
- }
-
- //定义Java和JNI函数的绑定表
- // 方法数组,分别为:(方法名[java层定义的],方法签名,函数指针[c层对应替换的方法])
- // 可以通过javac和javap 获取 方法签名
- JNINativeMethod method_table[] = {
- {"computer", "(Ljava/lang/String;II)I", (void *) native_computer},
- };
-
- int registerNativeMethods(JNIEnv *env, const char *className, JNINativeMethod *methods,
- int methods_size) {
- jclass clazz = NULL;
- //反射Java类
- clazz = (*env)->FindClass(env, className);
- if (NULL == clazz) {
- return JNI_ERR;
- }
- int result = (*env)->RegisterNatives(env, clazz, methods, methods_size);
- LOGD("registerNativeMethods result : %d", result);
- if (result < 0) {
- return JNI_ERR;
- }
- return JNI_OK;
- }
-
- JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved ){
- JNIEnv *env = NULL;
- int result = (*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_6);
- LOGD("JNI_OnLoad 1 result : %d", result);
- if(result != JNI_OK){
- return JNI_ERR;
- }
- result = registerNativeMethods(env, DYNAMIC_CLASS, method_table, ARRAY_LENGTH(method_table));
- LOGD("JNI_OnLoad 2 result : %d", result);
- if(result != JNI_OK){
- return JNI_ERR;
- }
- return JNI_VERSION_1_6;
- }
动态注册变动的比较少。其实完全可以封装。
上面都有注释,这里就懒得解释了。
参考文章
《》
© 版权声明