1. 程式人生 > 實用技巧 >java利用jni呼叫dll方法

java利用jni呼叫dll方法

準備工作:

需要用到的外掛jni4net:這個需要去官網下載:https://sourceforge.net/projects/jni4net/files/

(1) jni4net 是一個開源的專案

(2) jni4net-0.8.8.0.zip 中是工具的所有檔案,包含示例

下載後解壓是這樣的

開啟lib下邊有你需要用到的jar包和dll這是關鍵。

建立C#程式:

開啟vs建立一個類庫com.demo.lib專案,寫上測試程式。

HelloWorld.cs

result.cs

User.cs

編譯成功之後,會在bin下的Debug下生成相關的dll。

使用proxygen工具來生成proxy類.

jni4net-0.8.8.0-bin\bin下就有proxygen工具,可以直接在該目錄下開啟cmd,執行命令:.\proxygen.exe "DLL所在路徑" -wd "java專案根路徑"

此處我是直接在bin下建了一個資料夾,用於存放生成的檔案。生成之後,需要將所有檔案拷到java專案根路徑下。

執行後會出現以下檔案

然後將jni4net的相關檔案都拷到java專案的根路徑下,執行build.cmd

裡面的指令碼需要修改成你對應的專案路徑。

錯誤提示:

執行過程中如果提示你某些程式包不存在,說明你沒有放到專案路徑下,或者說,你沒有專案中沒有相關的jar包。

如果提示你csc.exe是不可執行的命令,說明你沒有配置環境變數,將PATH中加上路徑:C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319(環境變數之間用英文分號;隔開),其他方法也可以實現。

執行成功之後會生成一個dll一個jar。

這兩個是後邊需要用到的。

java部分

我採用的開發工具是IDEA,我在專案根目錄下,建了一個資料夾叫,lib,然後將兩個jar包拷到lib下面。記住此處要將jar包新增到專案中去。

dll的話,我是採用的第三方路徑,別的方法也可以,我簡單闡述一下我的方法。我將剩餘的dll拷到e盤下dll資料夾中,

然後在配置檔案中,配置上相關的路徑。

在application.yml加個配置資訊

 plugins:
dll:
path:
e:/dll #dll所在路徑
files: com.demo.lib.j4n.dll #載入的dll檔名,是生成的那個

由於我們是採用的外部資料夾的形式,因此需要一個類來初始化載入這個配置資訊。

測試程式:

新建一個demo.java的類,需要將之前讀取到的dll中的資訊讀取過去,因此需要這麼一個方法:

public List<String> loadPlugins()
{
Logger log = LoggerFactory.getLogger(PluginsLoader.class);
List<String> arr = new ArrayList<>();
String files=pluginsLoader.getFiles().trim();
String path=pluginsLoader.getPath();
if(files.length()>0)
{
File dir = new File(path);
if(dir.exists())
{
log.info("-------start loading plugins,directory is "+path+"-------");
try {
Bridge.init(dir);
String[] fileArr = files.split(",");
for (String f : fileArr) {
File file = new File(dir, f);
if (file.exists()) {
Bridge.LoadAndRegisterAssemblyFrom(file);
arr.add(f);
log.info("plugin loaded:"+f);
} else {
log.warn(f + " not exists,not loaded!");
}
}
log.info("------- load plugins complete -------");
}catch (IOException e)
{
log.error("init bridge failed:"+e.getLocalizedMessage());
}
}
}
return arr;
}
有了這個方法,你就可以呼叫了
直接上測試程式:
@RequestMapping("/dll")
public String invokeDllFunction()
{
List<String> arr = loadPlugins();
Result rs = null;
User u = new User();
u.setName("張三");
u.SetFirstName("first name");
rs = HelloWorld.StaticGreet(u,"message info");
HelloWorld hw = new HelloWorld();
Result rs2 = hw.Greet(u,"greet info");
return rs.getMessage()+","+rs2.getMessage();
}

示例中,Result、User、HelloWorld三個類都是dll中的,HelloWorld中有一個靜態方法,兩個過載方法,方法引數有類、字串,返回型別有void有物件。在c#程式碼中,User類有一個屬性private String Name{get;set},生成的jar中User的setName於getName是自動給加上的getter、setter;

好了,啟動試試吧:呼叫結果:

到這裡,基本上就完成了。

使用總結

1、執行指令碼,生成jar和dll

2、配置dll的路徑等資訊

3、將jar新增到java專案並使用

備註:

Springboot引入本地jar,並在生成時複製到對應lib下,對應pom.xml配置:

<dependency>
<groupId>net.sf</groupId>
<artifactId>jni4net</artifactId>
<version>0.8.8.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/libs/jni4net.j-0.8.8.0.jar
</systemPath>
</dependency>
<dependency>
<groupId>com.demo</groupId>
<artifactId>lib.j4n</artifactId>
<version>1.0.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/libs/com.demo.lib.j4n.jar
</systemPath>
</dependency>

<resources>
<resource>
<directory>${project.basedir}/libs</directory>
<targetPath>BOOT-INF/lib/</targetPath>
<filtering>false</filtering>
<includes>
<include>*.jar</include>
</includes>
</resource>
</resources>