Java通過JNA調用dll或so


前言

場景:某些功能已有C語言實現,現有Java業務系統需要引入。

這種情況下,如果用Java重寫一遍可能更加費時費力,不如將此C語言功能編譯為一個系統庫,供Java調用。

1 引入JNA

pom文件添加依賴

<!-- https://mvnrepository.com/artifact/net.java.dev.jna/jna -->
<dependency>
	<groupId>net.java.dev.jna</groupId>
	<artifactId>jna</artifactId>
	<version>4.5.2</version>
</dependency>

2 Windows系統調用dll

設dll文件名為libtest.dll,將其放置於此Java文件同文件夾下或項目resources目錄。

調用demo代碼

import com.sun.jna.Library;
import com.sun.jna.Native;

public class JavaCallDllDemo {

    public interface CLibrary extends Library {
        // DLL文件默認路徑為項目根目錄,若DLL文件存放在項目外,請使用絕對路徑
    	CLibrary INSTANCE = (CLibrary) Native.load("libtest", CLibrary.class);
        // 聲明將要調用的DLL中的方法(可以是多個方法)
        int add(int a, int b);
    }

    public static void main(String[] args) {
        int result = JavaCallDllDemo.CLibrary.INSTANCE.add(200, 300);
        System.out.println("result: " + result);
    }

}

注意這里代碼加載庫文件不需要帶dll后綴

3 Linux系統調用so

設so文件名為libtest.so,將其放置於/usr/lib下,或者自定義目錄,如/usr/local/lib

自定義目錄需要額外將其添加到環境變量

vim /etc/profile

在末尾添加

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib

刷新環境變量,使改動生效

source /etc/profile

調用demo代碼

import com.sun.jna.Library;
import com.sun.jna.Native;

public class JavaCallSoDemo {

    public interface CLibrary extends Library {
        // SO文件默認路徑為/usr/lib
    	CLibrary INSTANCE = (CLibrary) Native.load("test", CLibrary.class);
        // 聲明將要調用的so中的方法(可以是多個方法)
        int add(int a, int b);
    }

    public static void main(String[] args) {
        int result = JavaCallSoDemo.CLibrary.INSTANCE.add(200, 300);
        System.out.println("result: " + result);
    }

}

注意這里代碼加載庫文件不需要帶lib前綴和so后綴

4 兼容Windows和Linux調用

由上可以將代碼整合一下,自動判斷環境以決定調用名

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;

public class JavaCallDllSoDemo {

    public interface CLibrary extends Library {
        
    	CLibrary INSTANCE = (CLibrary) Native.load(Platform.isWindows() ? "libtest" : "test", CLibrary.class);
        
        int add(int a, int b);
    }

    public static void main(String[] args) {
        int result = JavaCallDllSoDemo.CLibrary.INSTANCE.add(200, 300);
        System.out.println("result: " + result);
    }

}

5 附,生成簡單dll/so

下面簡要說明如何自己生成dll/so,以供測試。

這里使用工具為Dev C++。

5.1 Windows下生成dll

自行下載Dev C++, 打開,點擊文件 -> 新建 -> 項目,選擇dll,C項目,名稱輸入libtest,確定。

新建dll項目

之后會生成一個dllmain.c文件和dll.h文件。

修改內容並保存:

dllmain.c文件

#include "dll.h"

DLLIMPORT int add(int a, int b)
{
	return a+b;
}

dll.h文件

#ifndef _DLL_H_
#define _DLL_H_

#if BUILDING_DLL
#define DLLIMPORT __declspec(dllexport)
#else
#define DLLIMPORT __declspec(dllimport)
#endif

DLLIMPORT int add(int a, int b);

#endif

如此,就聲明了一個方法,方法兩個int參數,返回兩數之和。

之后點擊運行 -> 編譯,會在項目目錄下生成libtest.dll文件。

5.2 Linux下生成so

將以上dllmain.c和dll.h文件稍作修改:

dllmain.c文件

#include "dll.h"

int add(int a, int b)
{
	return a+b;
}

dll.h文件

#ifndef _DLL_H_
#define _DLL_H_

#if BUILDING_DLL
#define DLLIMPORT __declspec(dllexport)
#else
#define DLLIMPORT __declspec(dllimport)
#endif

int add(int a, int b);

#endif

將兩個文件復制到linux中,執行gcc命令

gcc dllmain.c -fPIC -shared -o libtest.so

即在當前目錄下生成libtest.so文件。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM