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>