导航号,我的单页导航
文章目录

前言

之前JNI一直用C语言写,但发现Android Framework中大都用C++写,为了阅读方便,改为C++。其实C++跟C语言写法一样的,只不过C++更简洁些。

正文

修改点,举个例子

不同点

hello.c文件后缀改为hello.cpp,还有就是C++传入的参数更少,看起来更简洁。

hello.c
JNIEXPORT jstring JNICALL Java_com_biumall_jni_one_Hello_hello
  (JNIEnv * env , jclass jclazz){
    return (*env)->NewStringUTF(env, "Hello World !---from JNI");
};
hello.cpp
JNIEXPORT jstring JNICALL Java_com_biumall_jni_one_Hello_hello
  (JNIEnv * env , jclass jclazz){
    return env->NewStringUTF("Hello World !---from JNI");
};
Android.mk

下面有注释不同点

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_LDLIBS := -llog
LOCAL_MODULE    := Hello

# C语言
LOCAL_SRC_FILES := Hello.c
# C++ 
LOCAL_SRC_FILES := Hello.cpp

include $(BUILD_SHARED_LIBRARY)

C++版

代码跟《JNI动态注册封装C语言版》一样。只不过这里是C++版的。

PS :这里只是代码,具体动态注册流程请看《JNI动态注册

Hello.java
public class Hello {
    private final String TAG = "from_dynamic_java_";
    //1. load Hello.so
    static {
        System.loadLibrary("Hello");
    }
    // 2. define native computer()
    public static native int computer(String type, int a, int b);
    
    public int add(int x, int y) {
        return x + y;
    }
    public int sub(int x, int y) {
        return x - y;
    }
}
Log.h
#include <android/log.h>

//定义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__)
JNICommon.h
#include <jni.h>

//获取数组大小
#define ARRAY_LENGTH(x) ((int)(sizeof(x) / sizeof((x)[0])))

//注册本地方法
int registerNativeMethods(JNIEnv *env, const char *className, JNINativeMethod *methods,
                          int methods_size) {
    jclass clazz = env->FindClass(className);
    if (!clazz) {
        return JNI_ERR;
    }
    int result = env->RegisterNatives(clazz, methods, methods_size);
    if (result < 0) {
        return JNI_ERR;
    }
    return JNI_OK;
}
Hello.cpp
#include "JNICommon.h"
#include "Log.h"
#include<string.h>

/**
 * ---------------------------第一步 start ---------------------------
 * 定义Hello.java类路径[包名+类名,只不过.换成了/]
 * 包名+类名:com.biumall.dynamic.one.Hello
 */
#define DYNAMIC_CLASS "com/biumall/dynamic/one/Hello"
/**
 * ---------------------------第一步  end  ---------------------------
 */

/**
 * ---------------------------第二步 start ---------------------------
 * c_add()用于调用Java方法
 * @param env env
 * @param jclazz jclazz
 * @param x x
 * @param y y
 * @return
 */
int c_add(JNIEnv *env, jclass jclazz, int x, int y) {
    jmethodID methodID = env->GetMethodID(jclazz, "add", "(II)I");
    jobject object = env->AllocObject(jclazz);
    return env->CallIntMethod(object, methodID, x, y);
}

/**
 * c_sub()用于调用Java方法
 * @param env env
 * @param jclazz jclazz
 * @param x x
 * @param y y
 * @return
 */
int c_sub(JNIEnv *env, jclass jclazz, int x, int y) {
    jmethodID methodID = env->GetMethodID(jclazz, "sub", "(II)I");
    jobject object = env->AllocObject(jclazz);
    return env->CallIntMethod(object, methodID, x, y);
}

/**
 * 本地方法computer实现
 */
JNIEXPORT jint JNICALL native_computer(JNIEnv *env, jclass jclazz, jstring type, jint a, jint b) {
    const char *charType = env->GetStringUTFChars(type, 0);
    LOGD("native_computer : %s ", charType);
    int count;
    if (!strcmp(charType, "-")) {
        count = c_sub(env, jclazz, a, b);
    } else if (!strcmp(charType, "+")) {
        count = c_add(env, jclazz, a, b);
    }
    env->ReleaseStringUTFChars(type, charType);
    return count;
}
/**
 * ---------------------------第二步  end  ---------------------------
 */

/**
 * ---------------------------第三步 start ---------------------------
 * 定义Java和JNI函数的绑定表
 * 方法数组,分别为:(native方法 , 方法签名 , 函数指针[JNI中需要实现的方法名])
 * 通过javac和javap 获取 方法签名
 */
JNINativeMethod method_table[] = {
        {"computer", "(Ljava/lang/String;II)I", (void *) native_computer},
};
/**
 * ---------------------------第三步  end  ---------------------------
 */

/**
 * ---------------------------第四步 start ---------------------------
 * 注册本地方法
 */
JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved ){
    JNIEnv *env = NULL;
    int result = vm->GetEnv((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;
}
/**
 * ---------------------------第四步  end  ---------------------------
 */
Application.mk
APP_ABI := arm64-v8a
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_LDLIBS := -llog
LOCAL_MODULE    := Hello
LOCAL_SRC_FILES := Hello.cpp
include $(BUILD_SHARED_LIBRARY)

参考文章

  1. JNI动态注册封装C语言版

  2. JNI动态注册

© 版权声明
导航号,我的单页导航

暂无评论

暂无评论...