MATLAB混合编程
java调用MATLAB
- 在MATLAB中新建脚本,编写需要函数,此处仅做示例(作图)
Magic.m
function f =Magic( input )
f=magic(input);
end
Eig.m
function [v,d]=Eig(input)
format long
[v,d]=eig(input);
end
Plot.m
function Plot(x,y )
p=polyfit(x,y,3);
t=min(x):max(x)/100:max(x);
s=polyval(p,t);
plot(x,y,'*',t,s);
title('数据拟合结果');
xlabel('x');
ylabel('y');
end
- 在控制台输入 deploytool ,会打开一个Compiler窗口,选择第3个,Library Compiler,进入页面后左上角有个可以选着打包类型的,这里选java package,然后在右边选项框有个选择函数的+,点击左边那个加号可以添加函数,最后要注意的是最下面的有个class name ,这个名字是到时候你在java那边使用这个函数的类名,可以重命类名,这里直接使用默认的Class1 。最后点击Package就可。
1.选择java Package;
2.选择我们事先写好的脚本;
3.如果jar运行在安装matlab的电脑上打上第一个勾即可,若安装在无matlab的电脑上选上第二行的勾。
4.打包运行
5.类名和方法名
6.如果你要在没有安装matlab的机器上用java调用这些jar包,答案也是可以的,不过你要先在电脑上安装matlab提供的MATLAB Compiler Runtime (MCR) ,它的安装文件在D:\MATLAB\matlab\toolbox\compiler\deploy\win64下(你的安装目录下)文件名InstallAgent.zip里面。
- 然后就出错了,
问题一:
这个问题很重要,百度查到大多是这个问题,运行机器上必须装有JRE 并且版本要和MatLab自带的jre 大版本保持一致(位数也要保持一致)
- 查询MATLAB自带jre, 装的是MATLAB2016a,在MatLab中命令行窗口中输入 【version -java】 命令查看。如图所示:
-
验证系统jdk jre。 验证jdk,jre版本位数。打开cmd 输入命令 【java -version】
和 【javac -version】分别验证编译和运行版本。
可以发现MATLAB和机器上的版本并不一致,解决方法重装jdk,注意保持版本一致
- 打包完成之后如图,
我们需要的导入进MyEclipse中的jar包是在第二个文件中。然后要回到Java中实现它了。首先我们要在MATLAB的安装目录下找到javabuilder.jar,它是在你安装目录下的toolbox文件夹下javabuilder目录下的jar文件夹里,比如我这个jar包的路径就是D:\MATLAB\matlab\toolbox\javabuilder\jar,在我们接下来要测试这个jar包的工程中导入这个jar包和我们之前生成的jar包。
JAVA调用matlab程序
1.使用java调用Maltab函数的基本方法是:通过Java Builder实现Java调用Matlab。在Java环境中直接调用Matlab所生成的Jar包。
下面以在Java中产生任意维数的魔方矩阵,计算任意矩阵的特征向量和特征值,对两组数据进行拟合并绘制拟合曲线三个实例来说明通过Java Builder实现Java调用Matlab的过程。传统的纯Java编程实现上述实例非常复杂,甚至很难完成。这一问题在Matlab中只需要调用几个函数即可完成。
1. 函数调用
在打包中会看for_testing文件下这个类的java文件了,打开我们可以看到如下的信息:
/**
* Provides the standard interface for calling the <code>Magic</code> MATLAB function with
* 1 input argument.
* Input arguments may be passed as sub-classes of
* <code>com.mathworks.toolbox.javabuilder.MWArray</code>, or as arrays of
* any supported Java type. Arguments passed as Java types are converted to
* MATLAB arrays according to default conversion rules.
*
* @param nargout Number of outputs to return.
* @param rhs The inputs to the MATLAB function.
* @return Array of length nargout containing the function outputs. Outputs
* are returned as sub-classes of
* <code>com.mathworks.toolbox.javabuilder.MWArray</code>. Each output array
* should be freed by calling its <code>dispose()</code> method.
* @throws MWException An error has occurred during the function call.
*/
public Object[] Magic(int nargout, Object... rhs) throws MWException
{
Object[] lhs = new Object[nargout];
fMCR.invoke(Arrays.asList(lhs),
MWMCR.getRhsCompat(rhs, sMagicSignature),
sMagicSignature);
return lhs;
}
这正是我们在matlab写的程序调用它的方法,返回的类型是Obeject[] 也正是写的那个 Object[] result,那后面传参, int nargout可以看到注释的解释,指的就是MATLAB函数中对应的输出参数个数,所以输出的一个不定大小的二维矩阵这个参数也是1,而且nargout在印象里好像也是MATLAB里面的输出量。后面开始就是你对应MATLAB函数的传入参数了
a. 传入函数的JAVA变量先转换为运行时环境里的对象
例如:JAVA double对象转 matlab double对象(传入函数的实际是运行时环境提供的中间类型)
//把值先变成matlab能理解的double类型
a = new MWNumericArray(Double.valueOf(args1[0]), MWClassID.DOUBLE);
b = new MWNumericArray(Double.valueOf(args1[1]), MWClassID.DOUBLE);
a = new MWNumericArray(array, MWClassID.DOUBLE);
b. 函数调用
调用格式:
Object[] result = null;
// 用于保存计算结果。
//当返回矩阵有n个,则result[0]...result[n-1]分别是这些返回矩阵。
result = c1.myFunction(1, intput);
//调用matlab函数,第一个数表示输出多少个矩阵,输入1表示输出一个矩阵。 //输入2表示有两个输出矩阵,以此类推。输出多少个矩阵根据原先m文件的定义。 //input表示输入的矩阵,当需要多个输入矩阵时,可以input1,input2…
常规的输入矩阵:
MWNumericArray input = null; // 用于保存输入矩阵
在Java中调用Matlab的方法时,有三种方式。大致都有2个参数,第一个参数是定义输出结果,第二个参数为输入参数。
方式一:
input = MWNumbericArray.newInstance(int,int[],MWClassID.DOUBLE,MWComplexity.REAL);
//参数1表示矩阵的维数,参数2表示各维的大小即几行几列,参数三表示数据类型,参数四表示实数或复数
方式二:
double array[] = { 3, 2, 4, 5 };//要计算的数
//int array[]={3,2,4,5};也是可以的。
input = new MWNumericArray(array, MWClassID.DOUBLE);
result = c1.myFunction(1, intput);
输入二维矩阵:
double array[][] = { {3,2,4,5},{2,4,4,5} };//要计算的数,两行四列
//int array[][] = { {3,2,4,5},{2,4,4,5} };也是可以的。
//输入三维等多维矩阵同理。
input = new MWNumericArray(array, MWClassID.DOUBLE);
result = c1.myFunction(1, intput); //1代表返回值的个数为1
输出的Object[]处理
Object数组有多少元素由输出矩阵数决定
Object转换成MWNumericArray
例如:
MWNumericArray output = null; // 用于保存输出矩阵
output=(MWNumericArray) result[0];//将结果object转换成MWNumericArray
double res = output.getDouble(1);//从MWNumericArray对象中读取数据
后期处理,释放本地资源
MWArray.disposeArray(input);//建立的矩阵用这句
MWArray.disposeArray(output);// 建立的矩阵用这句
MWArray.disposeArray(result);//建立的Object数组用这句
c1.dispose();//建立的matlab类对象用这句
以上释放时,必须保证其不为null。
方式一最常用,
方式一:functionName(int arg0, Object… agr1): Object[]
Object[] result = null; // 用于保存计算结果,定义输出结果
GetEig getEig = null;
getMagic = new GetMagic();
result = getMagic.Magic(1,a);//2个参数,第一个参数1是定义输出结果为1个,第二个参数为输入参数是a。
System.out.println(result[0]); //输出返回内容
MATLAB封装dll
- 在控制台输入 deploytool ,会打开一个Compiler窗口,选择第3个库编译器Library Compiler,进入页面后左上角有个可以选着打包类型。
-
选择.NetAssembly,
-
那里点“+”好选择你要封装的m文件,
-
是封装后生成的dll的名字,
-
是在C#里你要调用MATLAB时需要创建的对象的类名,
-
是要调用的函数。
-
点击右上角封装打包
-
需要把这dll拷贝到C#的工程目录下,同时还要拷贝一份MWArray的dll,这个是C#专门针对调用MATLAB语言所设计的数据类型,如果不添加这个dll,那么在C#是无法调用MATLAB的。
另外,MWArray.dll 在matlab安装目录中,参考路径:D:\MATLAB\matlab\toolbox\dotnetbuilder\bin\win64\v4.0