1. 程式人生 > >程式碼告訴你:Java到底是怎麼呼叫dll&so動態庫的?

程式碼告訴你:Java到底是怎麼呼叫dll&so動態庫的?

使用Java呼叫dll&so動態庫的函式

*應用背景:專案中需要呼叫一項其他平臺提供的服務,是一位C語言老大哥寫的,可牛啦。但是因為一些特殊原因導致不能通過API呼叫的方式實現,最終的解決方案是老大哥把他的程式封裝成so和dll動態庫,然後我在專案裡使用JNA呼叫so或dll動態庫裡的函式。

1.在pom.Xml裡建立JNA框架依賴

<dependency>
		    <groupId>net.java.dev.jna</groupId>
		    <artifactId>jna</artifactId>
		    <version>4.1.0</version>
</dependency>

2.在Windows系統呼叫.dll動態庫
*作者是在Windows系統做開發的,所以在本機除錯的時候讓C的老大哥給我封裝了個dll檔案使用,方便你我他。
(1).程式碼實現
java呼叫dll檔案
(2).dll檔案的位置如下圖:
dll檔案位置

3.在linux系統呼叫.so動態庫
*專案開發完成後,部署到測試環境,我們的測試環境用的linux,所以老大哥又登入我們的測試伺服器熟練的封裝了so檔案。
(1).程式碼實現,與呼叫.dll檔案基本一致
java呼叫so檔案,紅框重點
(2).so檔案的位置如下圖:這個檔案必須等專案打成的war包解壓後手動放到classes目錄下,如果放在專案的resources目錄下直接打成war包使用,有可能會損壞so檔案。
so檔案位置


另外,我們的so檔案在初始化時,內部載入了其他的資源,這個資源位置必須在伺服器的執行目錄下,我們使用的tomcat,所以就放在了tomcat的bin目錄下

4.java和c的型別對映
介面中使用的函式必須與連結庫中的函式原型保持一致,這是JNA甚至所有跨平臺呼叫的難點,因為C/C++的型別與Java的型別是不一樣的,你必須轉換型別讓它們保持一致!
JNA官方給出的預設型別對映表如下:
型別對映
5.最後的原始碼留給你們

public interface CLibrary extends Library {

	//linux系統呼叫.so檔案,libline.so檔案一般放在編譯後的classes目錄下。注意,這裡只要寫line就可以
	了,不要寫libline,也不要加字尾
	
	CLibrary INSTANCE = (CLibrary)Native.loadLibrary("line", CLibrary.class);

    Void printf(String format);//對應.so檔案內封裝的函式
}

public static void main(String[] args) {
    CLibrary.INSTANCE.printf("test");
}

注:JNA是建立在JNI技術基礎之上的一個Java類庫,它使您可以方便地使用java直接訪問動態連結庫中的函式。原來使用JNI,你必須手工用C寫一個動態連結庫,在C語言中對映Java的資料型別,說白了就是得多寫一堆C程式碼。JNA中,它提供了一個動態的C語言編寫的轉發器,可以自動實現Java和C的資料型別對映,你不再需要編寫C動態連結庫。也許這也意味著,使用JNA技術比使用JNI技術呼叫動態連結庫會有些微的效能損失。但總體影響不大,因為JNA也避免了JNI的一些平臺配置的開銷。