NDK动态注册

3 篇文章 0 订阅

博客导航

c/c++和java交互,需要找到双方各自对应的函数或方法来调用。这种产生联系的方式有两种方式,一个是静态注册,另一种事动态注册。动态注册是比静态注册的好处是不需要JNI那一套很长的命名。

其他的规则和静态注册无异,只是注册的地方不同而已。

下面是动态注册的方式。

/**
 * 动态注册
 */
extern "C" {

jstring stringFromJNI2(JNIEnv *env, jobject instance) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

jint add(JNIEnv *env, jclass clazz, jint a, jint b) {
    LOGE("ADD!!");
    return a + b;

}

#define JNIREG_CLASS "com/slzr/ndk/NDKManager"//指定要注册的类
/**
* 方法对应表
*/
static JNINativeMethod gMethods[] = {
//        {"stringFromJNI2", "()Ljava/lang/String;", (void *) stringFromJNI2},
        {"add",            "(II)I",                (void *) add}
};

/*
* 为某一个类注册本地方法
*/
static int registerNativeMethods(JNIEnv *env, const char *className, JNINativeMethod *gMethods,
                                 int numMethods) {
    jclass clazz;
    clazz = env->FindClass(className);
    if (clazz == NULL) {
        return JNI_FALSE;
    }
    if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {
        return JNI_FALSE;
    }

    return JNI_TRUE;
}


/*
* 为所有类注册本地方法
*/
static int registerNatives(JNIEnv *env) {
    return registerNativeMethods(env, JNIREG_CLASS, gMethods,
                                 sizeof(gMethods) / sizeof(gMethods[0]));
}

/*
* System.loadLibrary("lib")时调用
* 如果成功返回JNI版本, 失败返回-1
*/
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
    JNIEnv *env = NULL;
    jint result = -1;
    if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
        return -1;
    }
    assert(env != NULL);
    if (!registerNatives(env)) {//注册
        return -1;
    }
    //成功
    result = JNI_VERSION_1_6;
    return result;
}
}

这里说明一下,JNI_OnLoadSystem.loadLibrary加载完动态库执行的函数,写在jni.h里面。
registerNatives写本地的方法。gMethods写方法列表,第一参数是java里面的方法名称,第二参数是方法输入参数,第三个参数是c/c++里面对应的函数。它的结构类型如下:

typedef struct {
    const char* name;
    const char* signature;
    void*       fnPtr;
} JNINativeMethod;

第二个参数可以参照java的反射。

字符 Java类型 C类型
V      void            void
Z       jboolean     boolean
I        jint              int
J       jlong            long
D      jdouble       double
F      jfloat            float
B      jbyte            byte
C      jchar           char
S      jshort          short
objects对象
以"L"开头,以";"结尾,中间是用"/" 隔开的包及类名。比如:Ljava/lang/String;如果是嵌套类,则用$来表示嵌套。例如 "(Ljava/lang/String;Landroid/os/FileUtils$FileStatus;)Z"

数组则以"["开始,用两个字符表示。
[I       jintArray      int[]
[F     jfloatArray    float[]
[B     jbyteArray    byte[]
[C    jcharArray    char[]
[S    jshortArray   short[]
[D    jdoubleArray double[]
[J     jlongArray     long[]
[Z    jbooleanArray boolean[]

gMethods里面的第二参数()表示输入参数,有多少就写多少进去。比如说两个int参数,就写(II)。括号后面跟着的是返回值V表示没有返回值void。Ljava/lang/String;对应是String类型。Ljava/lang/Object;对应是Object类型。

在java层面仍然需要native 编写。

    public native int add(int a, int b);

附件:
demo源码地址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值