1. 程式人生 > >JNI開發流程(Windows下)

JNI開發流程(Windows下)

目的

本次的目的是用java呼叫windows下C生成的.dll庫。

需要的工具 vs studio2013 ,eclipse

JNI(Java Native Interface):Java呼叫C/C++,C/C++呼叫Java的一套API

編寫native方法

首先寫一個java工程,程式碼如下:

public class JniTest {

    public native static String getStringFromC();

    public static void main(String[] args) {

    }
}
  • 我們通過javah命令生成一個頭檔案。配置jdk環境變數。
    這裡寫圖片描述
  • 切換到工程目錄這裡寫圖片描述

javah命令,生成.h標頭檔案

  • 使用javah命令生成 注意要是這個類的完整類名
    這裡寫圖片描述
  • 重新整理eclipse工程就會看見這個檔案

複製.h標頭檔案到CPP工程中

  • 我們在vsStudio中新建一個專案。
    這裡寫圖片描述
  • 新建一個類
    這裡寫圖片描述
  • 將生成的標頭檔案和新建的檔案放到一起。
    這裡寫圖片描述

實現.h標頭檔案中宣告的函式

  • 回到vsStudio 選中標頭檔案,然後新增->現有項,把jniTest_JniTest.h新增進去。
  • 我們檢視一下jniTest_JniTest.h,發現報錯。我們需要把jdk中的jni.h和新增進去。
    進入到jdk目錄
    這裡寫圖片描述

    搜尋jni.h
    這裡寫圖片描述
  • 在jniTest_JniTest.h中修改 #include <jni.h>#include "jni.h"儲存。
  • 我們在01.c檔案中可以編寫程式碼了。
#include "jniTest_JniTest.h"
//函式實現 C的函式名稱:Java_完整類名_函式名
JNIEXPORT jstring JNICALL Java_jniTest_JniTest_getStringFromC
(JNIEnv *env, jclass jcls){
    //簡單的實現
    //將C的字串轉換為一個java字串
    return (*env)->NewStringUTF(env,"C string"
); }

生成dll檔案

  • 接下來我們需要生成.dll檔案,通過vs生成。
    debug->配置管理器->在活動解決方案平臺中新建一個選項。
    這裡寫圖片描述
    因為我是64位作業系統,選擇:
    這裡寫圖片描述
    屬性這塊選擇生成dill動態庫(右鍵專案->屬性):
    這裡寫圖片描述
  • 生成-解決方案。
    這裡寫圖片描述
  • 之後就可以在eclipse中載入動態庫了
    如下程式碼:
public class JniTest {

    public native static String getStringFromC();

    public static void main(String[] args) {
        String stringFromC = getStringFromC();
        System.out.println(stringFromC);
    }
    //新增的動態庫。
    static {
        System.loadLibrary("JniProject");
    }
}

配置dll檔案所在目錄到windows系統的環境變數.

配置環境變數是為了找到庫的位置,
這裡寫圖片描述

或者直接放到eclipse的工程目錄下。也可以進行編譯

重啟Eclipse

最後將動態庫的位置配置到環境變數裡面就可以找到動態庫了

執行結果:
這裡寫圖片描述

一些簡要的知識點:

JNIEnv
- 在C中:
JNIEnv 結構體指標別名
env二級指標

在C++中:
JNIEnv 是一個結構體的別名
env 一級指標

c中,函式執行過程中需要傳入jnienv

JNIEXPORT jstring JNICALL Java_jniTest_JniTest_getStringFromC
(JNIEnv *env, jclass jcls){
    //簡單的實現
    //將C的字串轉換為一個java字串
    return (*env)->NewStringUTF(env,"C string");
}

C++,不用去傳,因為C++中有this關鍵字。

JNIEXPORT jstring JNICALL Java_jniTest_JniTest_getStringFromC
(JNIEnv *env, jclass jcls){
    //不用傳
    return env->NewStringUTF("C string");
}