JNI編程實現(Windows)

上一篇介紹了Linux平臺的JNI編程方法,Windows平臺的JNI本地調用基本類似,區別就是製作的動態庫不同,Linux平臺是*.soWindows平臺是*.dll。其中,Windows平臺的函數庫也分爲靜態庫和動態庫,下面介紹一下相關概念:

靜態庫
在鏈接步驟中,連接器將從庫文件取得所需的代碼,複製到生成的可執行文件中,這種庫稱爲靜態庫。其特點是可執行文件中包含了庫代碼的一份完整拷貝;缺點就是被多次使用就會有多份冗餘拷貝。即靜態庫中的指令都全部被直接包含在最終生成的EXE文件中了。在vs中新建生成靜態庫的工程,編譯生成成功後,只產生一個*.lib文件

動態庫
動態鏈接庫是一個包含可由多個程序同時使用的代碼和數據的庫,DLL不是可執行文件。動態鏈接提供了一種方法,使進程可以調用不屬於其可執行代碼的函數。函數的可執行代碼位於一個DLL中,該DLL包含一個或多個已被編譯、鏈接並與使用它們的進程分開存儲的函數。在vs中新建生成動態庫的工程,編譯成功後,產生一個.lib文件和一個.dll文件

那麼靜態庫中的lib和動態庫中的lib究竟有什麼區別呢?

靜態庫中的lib:該lib包含函數代碼本身(即包括函數的索引,也包括實現),在編譯時直接將代碼加入程序當中

動態庫中的lib:該lib包含了函數所在的dll文件和文件中函數位置的信息(索引),函數實現代碼由運行時加載在進程空間中的dll提供

本文製作動態庫,即生成*.lib*.dll文件,使用Visual Studio 2017工具,步驟和linux平臺的類似,下面詳細介紹

製作動態庫

1.編寫native聲明方法的java類

編寫Java類,聲明一個native的本地方法

public class Hello {
	public native static String sayHello(String name);

	static {
		System.load("E:\\Eclipse\\Hello\\libhello.dll");
	}

	public static void main(String[] args) {
		Hello hello = new Hello();
		String ret = hello.sayHello("kelvin");
		System.out.println(ret);
	}
}

2.編譯java類

使用javac進行編譯

#javac Hello.java

3.生成本地文件*.h

使用javah生成Hello.h頭文件,依賴上一步的Hello.class

# javah -jni Hello

4.使用Visual Studio 2017創建構建動態庫

接下來,使用Visual Studio 2017製作動態庫libhello.liblibhello.dll

a、新建工程

首先,新建工程,文件 -> 新建 -> 項目 -> Visual C++ -> Windows 桌面 -> 動態鏈接庫(DLL)

圖1

b、添加頭文件

把生成的本地頭文件Hello.h導入到工程中;另外,還需要把jni.hjni_md.h這兩個頭文件也導入到工程中

c、編寫本地方法的實現

新增Hello.cpp文件,編碼實現本地方法

#include "stdafx.h"
#include <iostream>
#include "Hello.h"

using namespace std;

JNIEXPORT jstring JNICALL Java_Hello_sayHello(JNIEnv *env, jclass jc, jstring name)
{
	const char *buf = { 0 };
	buf = env->GetStringUTFChars(name, NULL);

	cout << buf << endl;

	return env->NewStringUTF("hello");
}
d、生成動態庫

編譯工程,生成動態鏈接庫。如果是64位系統,還需要設置Debugx64,否則會報錯

生成 -> 重新生成解決方案

設置爲64位系統的動態庫

圖2

5、調用動態庫

把工程的根目錄下Debug中的libhello.dll拷貝到Hello.class目錄,如果是x64則是在目錄x64目錄下;然後,調用Hello測試jni的本地調用

# java -classpath E:\Eclipse\Hello Hello
kelvin
hello

看到輸出,表明了libhello.dll被正常加載調用了


這就是Windows的本地調用,雖然Java程序中提倡單一語言風格,但是本地調用提供了一種解決方案,在Java語言無法實現時,選擇使用jni也是一種合適的方式。

參考資料

java native方法與JNI實現
lib 和 dll 的區別、生成以及使用詳解

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章