JNI代码两种注册编写方式

样例java类
HelloJni.java

package com.example.test;

public class HelloJni {

    public native String  stringFromJNI();

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

方法一:静态注册

遵守JNI标准规函数命名方式, JNI中方法命名为 Java_包名_类名_方法名, 可以使用javah生成签名头文件, 靠这种方式实现Native方法与JNI方法之间的映射关系,即应用直接与框架层进行交互,这种规范常用与应用开发;

javah -jni 自动生成.h文件

<project>\bin\classes目录下执行

javah -classpath .;<sdkPath>\sdk\platforms\android-19\android.jar -jni com.pachong.test.Hello(pakageName.className)

即可生成对应的.h头文件,在这个头文件中就有我们需要实现的c&c++方法了,这里加上<sdkPath>\sdk\platforms\android-19\android.jar是因为我们的类中有引用到系统相关的一些类或方法需要加上android.jar才能生成对应.h文件。
这里写图片描述
com_example_test_HelloJni.h

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

#ifndef _Included_com_example_test_HelloJni
#define _Included_com_example_test_HelloJni
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_example_test_HelloJni
 * Method:    stringFromJNI
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_example_test_HelloJni_stringFromJNI
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

在项目根目录下新建jni文件夹,将刚刚生成的.h文件拷贝到这个目录下,同时新建一个对应的.cpp文件和Android.mk文件用于编译生成so文件。

com_example_test_HelloJni.cpp

/* DO NOT EDIT THIS FILE - it is machine generated */
#include "com_example_test_HelloJni.h"
/* Header for class com_example_test_HelloJni */

/*
 * Class:     com_example_test_HelloJni
 * Method:    stringFromJNI
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_example_test_HelloJni_stringFromJNI
  (JNIEnv *, jobject) {
    return env->NewStringUTF("Hello from JNI !");
}

Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := libhelloJni
LOCAL_SRC_FILES := com_example_test_HelloJni.cpp

include $(BUILD_SHARED_LIBRARY)

注:LOCAL_MODULE := libhelloJni要和System.loadLibrary(“helloJni”);对应起来。
这里写图片描述

javap -s -p 查看函数签名

-s: 显示签名(只显示public类型的签名) -p:显示所有函数、成员变量的签名

javap -classpath .;<sdkPath>\sdk\platforms\android-19\android.jar -s -p com.pachong.test.Hello(pakageName.className)

(注:<sdkPath>\sdk\platforms\android-19\android.jar是可选项),通过签名我们就可以在写jni相关的代码时写入相应的签名即可。
这里写图片描述

方法二:动态注册

这是Android自定义的一种规范, 应用框架层采用该规范, 即应用框架层 与 框架层 进行交互, 底层源码开发多使用该规范;

动态注册是通过调用JNI_OnLoad方法,去注册相关类的方法来实现的,来看下具体的实现。
customHelloJni.cpp

#include <jni.h>

static jstring  hello(JNIEnv* evn, jobject thiz) {
    return env->NewStringUTF("Hello from JNI !");
}

//需要调用实现JNI的类
static const char* classPathName = "com/example/test/HelloJni";

//绑定相应的方法
static JNINativeMethod methods[] = {
        {"stringFromJNI", "()Ljava/lang/String",(void*)hello},
};

//注册指定类的相关方法
static int registerNativeMethods(JNIEnv* env, const char* className, JNINativeMethod* gMethods, int numMethods) {
    jclass clazz;

    clazz = env->FindClass(className);
    if (class == NULL) {
        return JNI_FALSE;
    }

    if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {
        return JNI_FALSE;
    }

    return JNI_TRUE;
}

static int registerNatives(JNIEnv* env) {
    if (!registerNativeMethods(env, classPathName, methods, sizeof(methods)/sizeof(methods[0]))) {
        return JNI_FALSE;
    }

    return JNI_TRUE;
}

//注册JNI方法入口
jint JNI_OnLoad(JavaVM* vm, void* reserved) {

    JNIEnv* env = NULL;
    jint result = -1;

    if (vm->GetEnv(&env, JNI_VERSION_1_4) != JNI_OK) {
        return result;
    }

    if (registerNatives(env) != JNI_TRUE) {
        return result;
    }

    result = JNI_VERSION_1_4;
    return result;
}

通过上面的代码实现,我们知道动态注册比静态注册在实现函数命名上更加自由,我们不需要按照JNI的那套标准规则来命名相关方法,只需要在绑定方法函数时与Java类中方法对应即可,即JNINativeMethod数组中对应相应的方法关系即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值