久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

注冊(cè)JNI函數(shù)的兩種方式...

 oskycar 2021-02-18

前言

前面介紹過如何實(shí)現(xiàn)在Android Studio中制作我們自己的so庫(kù),,相信大家看過之后基本清楚如何在Android studio創(chuàng)建JNI函數(shù)并最終編譯成不同cpu架構(gòu)的so庫(kù),但那篇文章介紹注冊(cè)JNI函數(shù)的方法(靜態(tài)方法)存在一些弊端,,本篇將介紹另外一種方法(動(dòng)態(tài)注冊(cè))來克服這些弊端,。

注冊(cè)JNI函數(shù)的兩種方法

靜態(tài)方法

這種方法我們比較常見,但比較麻煩,,大致流程如下:
- 先創(chuàng)建Java類,,聲明Native方法,編譯成.class文件,。
- 使用Javah命令生成C/C++的頭文件,,例如:javah -jni com.devilwwj.jnidemo.TestJNI,則會(huì)生成一個(gè)以.h為后綴的文件com_devilwwj_jnidemo_TestJNI.h,。
- 創(chuàng)建.h對(duì)應(yīng)的源文件,,然后實(shí)現(xiàn)對(duì)應(yīng)的native方法,,如下圖所示:

這里寫圖片描述

說一下這種方法的弊端:

  • 需要編譯所有聲明了native函數(shù)的Java類,每個(gè)所生成的class文件都得用javah命令生成一個(gè)頭文件,。
  • javah生成的JNI層函數(shù)名特別長(zhǎng),,書寫起來很不方便
  • 初次調(diào)用native函數(shù)時(shí)要根據(jù)函數(shù)名字搜索對(duì)應(yīng)的JNI層函數(shù)來建立關(guān)聯(lián)關(guān)系,這樣會(huì)影響運(yùn)行效率
    摘自:深入理解Android卷I

既然有這么多弊端,,我們自然要考慮一下有沒有其他更好的方法下一節(jié)就是我要講的替代方法,,Android用的也是這種方法。

動(dòng)態(tài)注冊(cè)

我們知道Java Native函數(shù)和JNI函數(shù)時(shí)一一對(duì)應(yīng)的,,JNI中就有一個(gè)叫JNINativeMethod的結(jié)構(gòu)體來保存這個(gè)對(duì)應(yīng)關(guān)系,,實(shí)現(xiàn)動(dòng)態(tài)注冊(cè)方就需要用到這個(gè)結(jié)構(gòu)體。舉個(gè)例子,,你就一下子明白了:

聲明native方法還是一樣的:

public class JavaHello {
    public static native String hello();
}

創(chuàng)建jni目錄,,然后在該目錄創(chuàng)建hello.c文件,如下:

//
// Created by DevilWwj on 16/8/28.
//
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <jni.h>
#include <assert.h>

/**
 * 定義native方法
 */
JNIEXPORT jstring JNICALL native_hello(JNIEnv *env, jclass clazz)
{
    printf("hello in c native code./n");
    return (*env)->NewStringUTF(env, "hello world returned.");
}

// 指定要注冊(cè)的類
#define JNIREG_CLASS "com/devilwwj/library/JavaHello"

// 定義一個(gè)JNINativeMethod數(shù)組,,其中的成員就是Java代碼中對(duì)應(yīng)的native方法
static JNINativeMethod gMethods[] = {
    { "hello", "()Ljava/lang/String;", (void*)native_hello},
};


static int registerNativeMethods(JNIEnv* env, const char* className,
JNINativeMethod* gMethods, int numMethods) {
    jclass clazz;
    clazz = (*env)->FindClass(env, className);
    if (clazz == NULL) {
        return JNI_FALSE;
    }
    if ((*env)->RegisterNatives(env, clazz, gMethods, numMethods) < 0) {
        return JNI_FALSE;
    }
    return JNI_TRUE;
}

/***
 * 注冊(cè)native方法
 */
static int registerNatives(JNIEnv* env) {
    if (!registerNativeMethods(env, JNIREG_CLASS, gMethods, sizeof(gMethods) / sizeof(gMethods[0]))) {
        return JNI_FALSE;
    }
    return JNI_TRUE;
}

/**
 * 如果要實(shí)現(xiàn)動(dòng)態(tài)注冊(cè),,這個(gè)方法一定要實(shí)現(xiàn)
 * 動(dòng)態(tài)注冊(cè)工作在這里進(jìn)行
 */
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
    JNIEnv* env = NULL;
    jint result = -1;

    if ((*vm)-> GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
        return -1;
    }
    assert(env != NULL);

    if (!registerNatives(env)) { //注冊(cè)
        return -1;
    }
    result = JNI_VERSION_1_4;

    return result;

}

先仔細(xì)看一下上面的代碼,看起來好像多了一些代碼,,稍微解釋下,,如果要實(shí)現(xiàn)動(dòng)態(tài)注冊(cè)就必須實(shí)現(xiàn)JNI_OnLoad方法,這個(gè)是JNI的一個(gè)入口函數(shù),,我們?cè)贘ava層通過System.loadLibrary加載完動(dòng)態(tài)庫(kù)后,,緊接著就會(huì)去查找一個(gè)叫JNI_OnLoad的方法。如果有,,就會(huì)調(diào)用它,,而動(dòng)態(tài)注冊(cè)的工作就是在這里完成的。在這里我們會(huì)去拿到JNI中一個(gè)很重要的結(jié)構(gòu)體JNIEnv,,env指向的就是這個(gè)結(jié)構(gòu)體,,通過env指針可以找到指定類名的類,并且調(diào)用JNIEnv的RegisterNatives方法來完成注冊(cè)native方法和JNI函數(shù)的對(duì)應(yīng)關(guān)系,。

我們?cè)谏厦婵吹铰暶髁艘粋€(gè)JNINativeMethod數(shù)組,,這個(gè)數(shù)組就是用來定義我們?cè)贘ava代碼中聲明的native方法,我們可以在jni.h文件中查看這個(gè)結(jié)構(gòu)體的聲明:

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

結(jié)構(gòu)體成員變量分別對(duì)應(yīng)的是Java中的native方法的名字,,如本文的hello,;Java函數(shù)的簽名信息、JNI層對(duì)應(yīng)函數(shù)的函數(shù)指針,。

以上就是動(dòng)態(tài)注冊(cè)JNI函數(shù)的方法,,上面只是一個(gè)簡(jiǎn)單的例子,如果你還想再實(shí)現(xiàn)一個(gè)native方法,,只需要在JNINativeMethod數(shù)組中添加一個(gè)元素,,然后實(shí)現(xiàn)對(duì)應(yīng)的JNI層函數(shù)即可,,下次我們加載動(dòng)態(tài)庫(kù)時(shí)就會(huì)動(dòng)態(tài)的將你聲明的方法注冊(cè)到JNI環(huán)境中,而不需要你做其他任何操作,。

總結(jié)

關(guān)于JNI技術(shù),,在Android中使用是非常多的,我們?cè)趯?shí)際開發(fā)中或多或少可能會(huì)使用到第三方或者需要自己開發(fā)相應(yīng)的so庫(kù),,所以學(xué)習(xí)和理解JNI中的一些實(shí)現(xiàn)原理還是很有必要的,,從以前在Eclipse來實(shí)現(xiàn)so庫(kù)開發(fā)到現(xiàn)在可以通過Android Studio來開發(fā)so庫(kù),會(huì)發(fā)現(xiàn)會(huì)方便很多,,這個(gè)也是技術(shù)的發(fā)展帶來的一些便捷,。筆者也計(jì)劃學(xué)習(xí)NDK開發(fā)的相關(guān)技術(shù),后續(xù)也會(huì)將自己學(xué)到的內(nèi)容總結(jié)分享出來,。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多