<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                通過第一篇文章,大家明白了調用native方法之前,首先要調用System.loadLibrary接口加載一個實現了native方法的動態庫才能正常訪問,否則就會拋出java.lang.UnsatisfiedLinkError異常,找不到XX方法的提示。現在我們想想,在Java中調用某個native方法時,JVM是通過什么方式,能正確的找到動態庫中C/C++實現的那個native函數呢? **JVM查找native方法有兩種方式:** 1> 按照JNI規范的命名規則 2> 調用JNI提供的RegisterNatives函數,將本地函數注冊到JVM中。(后面會詳細介紹) 本文通過第一篇文章HelloWorld示例中的Java_com_study_jnilearn_HelloWorld_sayHello函數來詳細介紹第一種方式: ~~~ /* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_study_jnilearn_HelloWorld */ #ifndef _Included_com_study_jnilearn_HelloWorld #define _Included_com_study_jnilearn_HelloWorld #ifdef __cplusplus extern "C" { #endif /* * Class: com_study_jnilearn_HelloWorld * Method: sayHello * Signature: (Ljava/lang/String;)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_study_jnilearn_HelloWorld_sayHello (JNIEnv *, jclass, jstring); #ifdef __cplusplus } #endif #endif ~~~ ***JNIEXPORT 和 JNICALL的作用:*** 在上篇文章中,我們在將HelloWorld.c編譯成動態庫的時候,用-I參數包含了JDK安裝目錄下的兩個頭文件目錄: ~~~ gcc -dynamiclib -o /Users/yangxin/Library/Java/Extensions/libHelloWorld.jnilib jni/HelloWorld.c -framework JavaVM -I/$JAVA_HOME/include -I/$JAVA_HOME/include/darwin ~~~ 其中第一個目錄為jni.h頭文件所在目錄,第二個是跨平臺頭文件目錄(mac os x系統下的目錄名為darwin,在windows下目錄名為win32,linux下目錄名為linux),用于定義與平臺相關的宏,其中用于標識函數用途的兩個宏**JNIEXPORT**和?JNICALL,就定義在darwin目錄下的**jni_md.h**頭文件中。在Windows中編譯dll動態庫規定,如果動態庫中的函數要被外部調用,需要在函數聲明中添加__declspec(dllexport)標識,表示將該函數導出在外部可以調用。在Linux/Unix系統中,這兩個宏可以省略不加。這兩個平臺的區別是由于各自的編譯器所產生的可執行文件格式不一樣。這里有篇文章詳細介紹了兩個平臺編譯的動態庫區別:[http://www.cnblogs.com/chio/archive/2008/11/13/1333119.html](http://www.cnblogs.com/chio/archive/2008/11/13/1333119.html)。JNICALL在windows中的值為__stdcall,用于約束函數入棧順序和堆棧清理的規則。 Windows下jni_md.h頭文件內容: ~~~ #ifndef _JAVASOFT_JNI_MD_H_ #define _JAVASOFT_JNI_MD_H_ #define JNIEXPORT __declspec(dllexport) #define JNIIMPORT __declspec(dllimport) #define JNICALL __stdcall typedef long jint; typedef __int64 jlong; typedef signed char jbyte; #endif ~~~ **Linux下jni_md.h頭文件內容:** ~~~ #ifndef _JAVASOFT_JNI_MD_H_ #define _JAVASOFT_JNI_MD_H_ #define JNIEXPORT #define JNIIMPORT #define JNICALL typedef int jint; #ifdef _LP64 /* 64-bit Solaris */ typedef long jlong; #else typedef long long jlong; #endif typedef signed char jbyte; #endif ~~~ 從Linux下的jni_md.h頭文件可以看出來,JNIEXPORT 和 JNICALL是一個空定義,所以在Linux下JNI函數聲明可以省略這兩個宏。 **函數的命名規則:** 用javah工具生成函數原型的頭文件,函數命名規則為:Java_類全路徑_方法名。如Java_com_study_jnilearn_HelloWorld_sayHello,其中Java_是函數的前綴,com_study_jnilearn_HelloWorld是類名,sayHello是方法名,它們之間用 _(下劃線) 連接。 **函數參數:** JNIEXPORT jstring JNICALL Java_com_study_jnilearn_HelloWorld_sayHello(JNIEnv *, jclass, jstring); 第一個參數:JNIEnv* 是定義任意native函數的**第一個參數**(包括調用JNI的RegisterNatives函數注冊的函數),指向JVM函數表的指針,函數表中的每一個入口指向一個JNI函數,每個函數用于訪問JVM中特定的數據結構。 第二個參數:調用java中native方法的實例或Class對象,如果這個native方法是實例方法,則該參數是jobject,如果是靜態方法,則是jclass 第三個參數:Java對應JNI中的數據類型,Java中String類型對應JNI的jstring類型。(后面會詳細介紹JAVA與JNI數據類型的映射關系) **函數返回值類型:** 夾在JNIEXPORT和JNICALL宏中間的jstring,表示函數的返回值類型,對應Java的String類型 **總結:** 當我們熟悉了JNI的native函數命名規則之后,就可以不用通過javah命令去生成相應java native方法的函數原型了,只需要按照函數命名規則編寫相應的函數原型和實現即可。 比如com.study.jni.Utils類中還有一個計算加法的native實例方法add,有兩個int參數和一個int返回值:public native int add(int num1, int num2),對應JNI的函數原型就是:JNIEXPORT jint JNICALL Java_com_study_jni_Utils_add(JNIEnv *, jobject, jint,jint);?
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看