<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、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                ### 14.1 JNI的開發流程 JNI的開發流程有如下幾步,首先需要在Java中聲明native方法,接著用C或者C++實現native方法,然后就可以編譯運行了。 * 1.在Java中聲明native方法 創建一個類,這里叫做JniTest.java,代碼如下所示。 package com.ryg; import java.lang.System; public class JniTest { static { System.loadLibrary("jni-test"); } public static void main(String args[]) { JniTest jniTest = new JniTest(); System.out.println(jniTest.get()); jniTest.set("hello world"); } public native String get(); public native void set(String str); } 可以看到上面的代碼中,聲明了兩個native方法:get和set(String),這兩個就是需要在JNI中實現的方法。在JniTest的頭部有一個加載動態庫的過程,其中jni-test是so庫的標識,so庫完整的名稱為libjni-test.so,這是加載so庫的規范。 * 2.編譯Java源文件得到cIass文件,然后通過javah命令導出JNI的頭文件 具體的命令如下: javac com/ryg/JniTest.java javah com.ryg.JniTest 在當前目錄下,會產生一個com_ryg_JniTest.h的頭文件,它是javah命令自動生成的,內容如下所示。 /* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_ryg_JniTest */ #ifndef _Included_com_ryg_JniTest #define _Included_com_ryg_JniTest #ifdef __cplusplus extern "C" { #endif /* * Class: com_ryg_JniTest * Method: get * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_ryg_JniTest_get (JNIEnv *, jobject); /* * Class: com_ryg_JniTest * Method: set * Signature: (Ljava/lang/String; )V */ JNIEXPORT void JNICALL Java_com_ryg_JniTest_set (JNIEnv *, jobject, jstring); #ifdef __cplusplus } #endif #endif 上面的代碼需要做一下說明,首先函數名的格式遵循如下規則:Java_包名_類名_方法名。比如JniTest中的set方法,到這里就變成了JNIEXPORT void JNICALL Java_com_ryg_JniTest_set(JNIEnv *, jobject, jstring),其中com_ryg是包名,JniTest是類名,jstring是代表的是set方法的String類型的參數。關于Java和JNI的數據類型之間的對應關系會在14.3節中進行介紹,這里只需要知道Java的String對應于JNI的jstring即可。JNIEXPORT、JNICALL、JNIEnv和jobject都是JNI標準中所定義的類型或者宏,它們的含義如下: * · JNIEnv*:表示一個指向JNI環境的指針,可以通過它來訪問JNI提供的接口方法; * · jobject:表示Java對象中的this; * · JNIEXPORT和JNICALL:它們是JNI中所定義的宏,可以在jni.h這個頭文件中查找到。 下面的宏定義是必需的,它指定extern "C"內部的函數采用C語言的命名風格來編譯。否則當JNI采用C++來實現時,由于C和C++編譯過程中對函數的命名風格不同,這將導致JNI在鏈接時無法根據函數名查找到具體的函數,那么JNI調用就無法完成。更多的細節實際上是有關C和C++編譯時的一些問題,這里就不再展開了。 #ifdef __cplusplus extern "C" { #endif * 3.實現JNI方法 JNI方法是指Java中聲明的native方法,這里可以選擇用C++或者C來實現,它們的實現過程是類似的,只有少量的區別,下面分別用C++和C來實現JNI方法。首先,在工程的主目錄下創建一個子目錄,名稱隨意,這里選擇jni作為子目錄的名稱,然后將之前通過javah生成的頭文件com_ryg_JniTest.h復制到jni目錄下,接著創建test.cpp和test.c兩個文件,它們的實現如下所示。 // test.cpp #include "com_ryg_JniTest.h" #include <stdio.h> JNIEXPORT jstring JNICALL Java_com_ryg_JniTest_get(JNIEnv *env, jobject thiz) { printf("invoke get in c++\n"); return env->NewStringUTF("Hello from JNI ! "); } JNIEXPORT void JNICALL Java_com_ryg_JniTest_set(JNIEnv *env, jobject thiz, jstring string) { printf("invoke set from C++\n"); char* str = (char*)env->GetStringUTFChars(string, NULL); printf("%s\n", str); env->ReleaseStringUTFChars(string, str); } // test.c #include "com_ryg_JniTest.h" #include <stdio.h> JNIEXPORT jstring JNICALL Java_com_ryg_JniTest_get(JNIEnv *env, jobject thiz) { printf("invoke get from C\n"); return (*env)->NewStringUTF(env, "Hello from JNI ! "); } JNIEXPORT void JNICALL Java_com_ryg_JniTest_set(JNIEnv *env, jobject thiz, jstring string) { printf("invoke set from C\n"); char* str = (char*)(*env)->GetStringUTFChars(env, string, NULL); printf("%s\n", str); (*env)->ReleaseStringUTFChars(env, string, str); } 可以發現,test.cpp和test.c的實現很類似,但是它們對env的操作方式有所不同,因此用C++和C來實現同一個JNI方法,它們的區別主要集中在對env的操作上,其他都是類似的,如下所示。 C++:env->NewStringUTF("Hello from JNI ! "); C: (*env)->NewStringUTF(env, "Hello from JNI ! ") * 4.編譯so庫并在Java中調用 so庫的編譯這里采用gcc,切換到jni目錄中,對于test.cpp和test.c來說,它們的編譯指令如下所示。 C++:gcc -shared -I /usr/lib/jvm/java-7-openjdk-amd64/include -fPIC test.cpp -o libjni-test.so C: gcc -shared -I /usr/lib/jvm/java-7-openjdk-amd64/include -fPIC test.c -o libjni-test.so 上面的編譯命令中,/usr/lib/jvm/java-7-openjdk-amd64是本地的jdk的安裝路徑,在其他環境編譯時將其指向本機的jdk路徑即可。而libjni-test.so則是生成的so庫的名字,在Java中可以通過如下方式加載:System.loadLibrary("jni-test"),其中so庫名字中的“lib”和“.so”是不需要明確指出的。so庫編譯完成后,就可以在Java程序中調用so庫了,這里通過Java指令來執行Java程序,切換到主目錄,執行如下指令:java -Djava.library.path=jni com.ryg.JniTest,其中-Djava.library.path=jni指明了so庫的路徑。 首先,采用C++產生so庫,程序運行后產生的日志如下所示。 invoke get in c++ Hello from JNI ! invoke set from C++ hello world 然后,采用C產生so庫,程序運行后產生的日志如下所示。 invoke get from C Hello from JNI ! invoke set from C hello world 通過上面的日志可以發現,在Java中成功地調用了C/C++的代碼,這就是JNI典型的工作流程。
                  <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>

                              哎呀哎呀视频在线观看