前言
由于MATLAB在数值计算方面的高性能,大大提高了科研和工作的效率,已逐渐发展成一个具有较高通用性的、带有众多实用工具的运算操作平台。MATLAB中封装了种类齐全、功能强大的函数和工具箱等,MATLAB与Java的混合编程能帮助我们减少许多编写代码的时间,特别是在已经编写好MATLAB程序,需要用Java进行封装形成一个可运行的独立程序的时候,这样做则方便得多。要实现这个功能则需要安装并配置好Java环境以及MATLAB软件,利用MATLAB的编译功能打包jar,然后在Java工程中进行调用。以下是详细介绍。
1.准备工作
1.1 安装MATLAB
首先当然需要安装好MATLAB,已经成功安装并解决证书问题的可以跳过这一步骤。MATLAB R2014a下载与安装网上用很多教程,也可以通过我的百度网盘下载,里面有安装及key证书说明。由于某些原因这种分享容易失效,请关注文末的本人公众号“AI技术研究与分享”,并回复关键字“MATLAB R2014a”获取:
1.2 安装jdk
MATLAB打包成jar包时需要调用javac生成class文件,因此我们需要安装JDK。由于编译过程中的可能报错,大多是由于MATLAB的版本与JDK的版本不一致所导致的,根据情况需要降低JDK版本,经试验,MATLAB 2015a、2014a 适用jdk1.7 ,MATLAB 2013a 适用jdk1.6,其他的未测试(jdk1.8可能报错)。
jdk的安装步骤网上有许多教程可供参考,限于篇幅,这里就不作介绍了。值得注意的是,环境变量务必配置正确,否则后面的编译过程极易报错。
2. 打包步骤
这里我以一个简单的m程序打包作为例子,介绍其详细步骤供参考。
一、在MATLAB中编写m文件(写成m函数形式)并调试通过,我写好的MATLAB程序如下图所示
要打包的函数是test.m,其中调用了maxMum.m函数,上面的代码如下
test.m文件:
matlab function [Mean,Sum,Std,result]=test(input1,input2) Mean=mean(input1); Sum=sum(input1); Std=std(input1); result=maxMum(input1,input2); end maxMum.m文件: matlab function result=maxMum(a,b) Maxb=max(max(b)); result=double(a>Maxb); end
二、在MATLAB命令行窗口输入deploytool并回车,在跳出的编译器选择界面选择Library Compiler
如下图所示
三、弹出的编辑界面如下图
1.在界面1号框内选择Java Package;
2.点击2号框内的加号选择要打包的文件;
3.在3号框内设置包名;
4.在4号框内修改类名及方法名(为了方便调用,建议修改默认的类名)
5.第5、6号框内分别是运行时所需要的文件和一起安装的文件,一般会系统自动检测并添加进去;
6.点击7号框内的Package按钮进行打包,界面如下
四、等待打包完成,此时会出现三个文件夹如下所示
上面都完成后,若无错误,将默认在当前m文件所在目录生成以包名命名的文件夹,在for_testing文件夹内有我们需要的jar文件。
3. 调用jar包
3.1 调用方式
打包完成我们还是有必要了解下生成的这几个文件,for_testing文件夹中除了jar文件还有m文件转换的对应java程序,例如打开for_testing文件夹下的test(先前编译时自设的包名)文件夹,就有我们想要的Test类的java文件,打开可查看代码以及调用方式。
除了上述方式可以查看调用方法,还有更简单的方式。打开在生成文件夹下路径为for_redistribution_files_only\doc\html\index.html文件,可以查看test所有重载函数的使用说明,如下
这里最适合的方法是红色框圈出的,该方法的调用说明如下
解读:
参数nargout: 第一个输入参数是整形,表示的是输出的个数,在本例中有四个输出(Mean,Sum,Std,result),因此设置为4;
参数rhs: 与M函数对应的输入参数,为Object类型,本例中有两个输入参数(input1,input2)。虽说Object类是Java中其他所有类的基类,这里的两个参数是数组、int型等类型都是可以的,但建议使用MWNumericArray类型,后面详细介绍;
函数返回值: 一个包含nargout个返回参数的Object类型数组,每个元素对应M函数中的每个输出结果。
3.2 具体步骤
有了以上的基本认识,终于可以开始正式使用jar包了。
一、新建java工程,新建一个java程序用于使用jar包,添加必要的Jar包
因为是MATLAB打包的jar包,需要依赖MATLAB中的相关函数,所以需要的Jar包除了我们前面生成的test.jar包还要 javabuilder.jar 包,它的路径在MATLAB的安装目录下的toolbox\javabuilder\jar\javabuilder.jar,可以将两个jar包拷出来放到一个自建的文件夹中,方便下面添加jar包。
1.在新建的工程文件夹右击选择Properties进入属性界面
2.选择左侧Java Build Path(1号框),点击右边的Libraries(2号框),点击Add External JARs(3号框),找到上面说的javabuilder.jar和test.jar包的路径将两个包添加进库中(4号框)
3.点击右下角OK按钮,完成jar包添加。
二、在新建的java程序中导入包,即输入以下代码
java import com.mathworks.toolbox.javabuilder.*; import test.Test;//此处的test为前面编译时设置的包名,Test为选定的类名
三、在主方法中调用函数,输入如下代码
java import java.util.ArrayList; import com.mathworks.toolbox.javabuilder.*; import test.Test;//此处的test为前面的包名,Test为选定的类名 /** 在java中调用matlab转的jar包示例 * @author W.X * @version 1.0 10/5/2018 * */ public class Main { public static void main(String[] args) { MWNumericArray input1 = null;// 输入参数一 MWNumericArray input2 = null;// 输入参数二 Object[] result = null; // 输出结果 Test test = null; try { ArrayList<Integer> list = new ArrayList<>(); for (int i = 0; i < 15; i++){ list.add(i+1); } // 参数一为一个从1到15的数组 input1 = new MWNumericArray(list.toArray(), MWClassID.DOUBLE); // 参数二为10 input2 = new MWNumericArray(Double.valueOf(10), MWClassID.DOUBLE); test = new Test();// 实例化 result = test.test(4, input1,input2);// 调用test方法 double Mean=((MWNumericArray) result[0]).getDouble(1);// 第一个输出 double Sum=((MWNumericArray) result[1]).getDouble(1); // 第二个输出 double Std=((MWNumericArray) result[2]).getDouble(1); // 第三个输出 double[] R =new double[15]; // 第四个输出,为一个数组 for(int i=0;i<15;i++){ R[i]=((MWNumericArray) result[3]).getDouble(i+1); // 从result中依次取出第四个输出 System.out.println(R[i]); } // 打印结果 System.out.println(Mean); System.out.println(Sum); System.out.println(Std); } catch (MWException e) { e.printStackTrace(); } finally { MWArray.disposeArray(input1); MWArray.disposeArray(input2); MWArray.disposeArray(result); test.dispose(); } } }
代码说明:
代码看似较长,其实非常简单。代码11-14行声明了所有参数及对象,17-26行是对两个输入参数赋值。对于MATLAB来说原m函数中的两个输入参数可以是数组也可以是某个数,在java中调用时同样如此,作为示例这里我的第一个参数是个数组,第二个参数是一个实数。数组采用的是ArrayList型,实数是double型,两个参数都转化成MWNumericArray的类型进行调用。
代码第30行,调用test方法得到结果,结果保存在result的Object数组中。第32-34行依次从result的每个元素中取出第一、二、三个结果(Mean、Sum、Std),由于result是Object型而我们往往需要的是double型的结果数据,因此需要进行类型转换转换为MWNumericArray型然后引用其getDouble方法转化成double。
代码第36-40行,取出第四个结果并放在double型数组R中,由于第四个结果是数组型所以取出时需要借助循环结构依次赋值取出。