java中没有直接调用matlab的接口函数,在通常的情况下我们是通过借用C++作为中间过程来实现的,使用C++主要是用c与matlab的结构实现c调用matlab的功能,将这些功能函数封装成dll文件,用java语言调用所生成的dll文件,从而实现了调用matlab的功能。
java调用c程序利用的是java的jni技术,即java native interface。具体的过程为:
1.首先,写一个类:
public class Eng{
static{
System.loadLibrary("Eng"); // (1)
}
public native void plottest(); // (2)
}
这个类实现的是调用后面生成的Eng.dll这个动态连接库的功能。在dos环境下编译
java Eng.java
编译后使用jdk中的javah命令生成jni的头文件
javah -jni Eng
在本目录下就生成了Eng.h这个头文件
2.打开vc++6.0新建一个dll的工程名字叫Eng,这个工程名必须和System.loadLibrary("Eng")中的一样,因为编译生成的dll的名字就是这个工程的名字。
然后在vc++的环境中添加能够调用matlab的功能所需要的lib和一些环境的设置。
(1)Tools->Options->Directories中engine.h所在的路径,笔者所使用的路径为:C:\JDK1.5.0\INCLUDE,在这个对话框中的"Show directories for:"的下拉菜单中选择Library Files,然后添加库文件的路径,在笔者的计算机上的路径是:E:\MATLAB\EXTERN\LIB\WIN32\MICROSOFT\MSVC60。
(2)Project->Settings->Link在Object/Library Modules中加上库文件连接:
也就是自己手动添加三个文件分别是:
libmx.lib libmex.lib libeng.lib
(3)将通过javah生成的Eng.h文件拷贝到工程目录中,然后再FileView中导入到工程中,创建新的c++文件为Eng.cpp,用于实现用于上面的头文件中的函数。指定了engine的头文件所在的路径,所以就可以包括这个头文件了。同时加入其它的头文件就可以了。
具体的cpp文件内容为:
/* Eng.h */
#include "engine.h"
#include "stdlib.h"
#include "stdio.h"
#include "string.h"
#include "windows.h"
#include "Eng.h"
static double Areal[6]={1,2,3,4,5,6};
JNIEXPORT void JNICALL Java_Eng_plottest
(JNIEnv * eng, jobject obj){
Engine * ep;
mxArray * T=NULL,*a=NULL,*d=NULL;
char buffer[30];
double *Dreal,*Dimag;
double time[10]={0,1,2,3,4,5,6,7,8,9};
if (!(ep=engOpen(NULL))) {
MessageBox((HWND)NULL,(LPSTR)"can't start Matlab engine",(LPSTR)"Engwindemo.c",MB_OK);
exit(-1);
}
T=mxCreateDoubleMatrix(1,10,mxREAL);
memcpy((char *)mxGetPr(T),(char *)time,10*sizeof(double));
engPutVariable(ep,"T",T);
engEvalString(ep,"D=.5*(-9.8).*T.^2;");
engEvalString(ep,"plot(T,D);");
engEvalString(ep,"title('Position');");
engEvalString(ep,"xlabel('Time(seconds)');");
engEvalString(ep,"ylabel('Position(meters)');");
a=mxCreateDoubleMatrix(3,2,mxREAL);
memcpy((char *)mxGetPr(a),(char * )Areal,6*sizeof(double));
engPutVariable(ep,"A",a);
engEvalString(ep,"d=eig(A*A');");
engOutputBuffer(ep,buffer,30);;
engEvalString(ep,"whos");
MessageBox((HWND)NULL,(LPSTR)buffer,(LPSTR)"Matlab-whos",MB_OK);
d=engGetVariable(ep,"d");;
engClose(ep);
if (d==NULL) {
MessageBox((HWND)NULL,(LPSTR)"Get Array Failed",(LPSTR)"Engwindemo.c",MB_OK);
}else
{
Dreal=mxGetPr(d);
Dimag=mxGetPi(d);
if (Dimag) {
sprintf(buffer,"Eigenval 2:%g+%gi",Dreal[1],Dimag[1]);
}
else{
sprintf(buffer,"Eigenval 2:%g",Dreal[1]);
}
MessageBox((HWND)NULL,(LPSTR)buffer,(LPSTR)"Engwindemo.c",MB_OK);
mxDestroyArray(d);
}
mxDestroyArray(T);
mxDestroyArray(a);
}
编译这个工程在Debug文件夹中生成一个Eng.dll的文件
3.编写一个测试的java文件:
/* testEng.java */
public class testEng{
public static void main(String [] args)
{
Eng ad=new Eng();
ad.plottest();
}
}
同时将生成的Eng.dll文件和这个testEng.java放在同一个目录中,在dos环境下编译运行这个java程序。效果就出来了。
根据预测系统的需要,现在希望能在Java中直接调用Matlab的函数。但,搜索几时,找到的都是在Matlab中调用java的方法,只看到如下一篇文章中提到:在Matlab的新版中提供了此功能的初体验!
但最新版的Matlab是必不太好找,只好想法用java的jni接口,调用C,使用C去调用Matlab了。这样效率就牺牲了,真是没辙!
MATLAB的最新版本2006b中新添了一个产品-MATLAB Builder for Java。其实本来Matlab就有Java外部程序接口,不过原来的接口只能在.m文件中调用Java,而无法在Java程序中调用Matlab。新的Java Builder为我们在Java程序中调用Matlab丰富的数值计算资源提供了极大的便利。
与MATLAB对其他程序的外部接口相比,我觉得Java接口在一下几个方面比较有特色:
(1)在.m文件中可以直接调用Java资源。例如可以调用JDK中的界面元素构建用户界面。
(2)可以利用Java在网络功能方面的优势,开发基于Web的应用程序。
由于Java Builder是个新产品,我也是相应 bainhome版主的号召,现炒现卖:),旨在抛砖引玉,引发有兴趣的网友的共同讨论。错误之处敬请批评指正。
什么是MATLAB Builder for Java?
MATLAB Builder for Java(又叫Java Builder)是对MATLAB Compiler的扩展。用Java Builder可以将MATLAB函数包装到一个或多个Java类中形成一个Java组件或包。每个MATLAB函数被封装为Java类的一个方法,可以在Java应用程序中被调用。
环境变量设置
为了使用Java Builder来进行开发,你的计算机上必须安装有JDK,而且必须对自己计算机的环境变量进行必要的设置,具体步骤如下:
(1)点击 开始->右击“我的电脑”,选择“属性”。在弹出的“系统属性”对话框中选择“高级”标签,然后点击下发的“环境变量”按钮。
(2)设置JAVA_HOME 变量
a. 点击弹出的对话框中上方的“新建”按钮;
b. 变量名:JAVA_HOME;
c. 变量值:JDK的安装目录,需要设置为javac.exe的上一层目录。例如我的机器上javac.exe在C:\Sun\AppServer\jdk\bin中,那么JAVA_HOME的变量值应设为C:\Sun\AppServer\jdk。
d. 点击“确定”。
(3)设置CLASSPATH变量
a. 点击“新建”
b. 变量名:CLASSPATH
c. 变量值:.;matlabroot\toolbox\javabuilder\jar\javabuilder.jar;
d. 点击“确定” 。
(4)“确定”,“确定”,退出属性设置。
说明:进行完上述设置后就可以用Java Builder简单的开发了。但需要说明的是,如果你的Java程序中还调用了其他的.jar包,则应该在CLASSPTH中进行相应的设置。
用Java Builder创建Java组件的步骤
为了创建组件您需要写好M-代码(或使用已有代码),然后在MATLAB的Java编译器中创建一个项目来对代码进行封装。一般步骤如下:
1. 编写、测试并保存用来创建Java组件的MATLAB代码。
2. 对计算机的环境变量进行必要的设置。详见Settings for Environment Variables (Development Machine)。
3.在MATLAB中,执行下列命令打开 Deployment 工具:
deploytool
4.用 Deployment 工具创建包含一个或多个类的项目。
a. 点击工具栏上的新建项目图标创建项目。
b. 设定项目名称和位置。
默认的项目名称为将要创建的包名。您可以更改这一默认值。
c. 为Java包中将要创建的类添加类名。
d. 为每个类添加要封装到该类中的一个或多个M-文件。
e. 根据需要为类添加辅助文件。
f. 保存项目。
5. 对包进行编译
在项目的编译过程中会复制项目的\src子目录下的Java包装类,同时复制项目\distrib子目录下的.jar文件和.ctf文件。\distrib目录下的文件定义了您的Java组件。
.ctf文件是组件技术文件,在没有安装MATLAB桌面的用户机器上运行封装有MATLAB函数的组件时需要该文件。
6. 对组件进行测试,根据需要对其进行重编译。
您或许想在将组件用于应用程序之前或准备提供给他人使用之前对其进行测试。在您的开发平台上测试过组件后,您可以根据需要重新打开项目继续下一步操作。
7. 创建一个包来将组件和其他必要文件发布给开发人员。这一步骤仅当您想将组件供不同开发机器上的其他应用程序开发人员使用时才需要。
8. 保存项目
Java Builder将项目保存到一个.prj文件中。
注:上述内容翻译自MATLAB的帮助文件。
一个简单的例子
下面用taohe帖子[url]http://www.simwe.com/forum/thread-746989-1-2.html[/url]中同样m文件,来演示如何通过Java Builder在Java程序中调用该文件。
[size=3][b]Matlab Codes:[/b][/size]
function y = myadd(a, b)
y = a+b;
end
步骤如下:
1. 在Editor中编写如上代码,并保存为myadd.m;
2. 在Command Window中执行deploytool,打开Deployment tool窗口。
3. 点击Deployment tool窗口工具栏最左边的新建图标,打开New Deployment Project 对话框。从左边选择“MATLAB Builder for Java”,得到如下画面:
4. Name栏填myadd.prj。点击“Ok"按钮。
5. 将myadd.m拖入myaddclass中,如下图所示。然后点击工具栏上的保存按钮,保存项目。
6. 点击Deployment tool 窗口工具栏上的Build the Project 图标编译项目。编译完成后在你的工作目录上会出现一个myadd文件夹,其中有两个名称分别为distrib和src的文件夹。distrib中的文件就是Java Builder生成的可发布文件。共有两个文件:myadd.jar和myadd.ctf。
7. 将MATLAB的当前目录切换到distrib目录。用winrar等软件将myadd.jar “解压到当前文件夹”。解压后你会看到两个文件夹:META-INF和myadd。如下图所示:
8. 在Matlab的Editor中新建一文件。输入下面的内容,并保存为MJBuilderTest.java。 (注意扩展名)
/* Necessary package imports */
import com.mathworks.toolbox.javabuilder.*;
import myadd.*;
/*
* MJBuilderTest class test the myadd class created by Java Builder. The
* inputs are passed on the command line.
*/
class MJBuilderTest
{
public static void main(String[] args)
{
MWNumericArray a = null; /* Stores input values a */
MWNumericArray b = null; /* Stores input values b */
Object[] result = null; /* Stores the result */
myaddclass myAdd = null; /* Stores myadd class instance */
try
{
/* 检测输入变量 */
if (args.length != 2)
{
System.out.println("Error: must input 2 numbers!");
return;
}
/* 接收输入变量 */
a = new MWNumericArray(Double.valueOf(args[0]),MWClassID.DOUBLE);
b = new MWNumericArray(Double.valueOf(args[1]),MWClassID.DOUBLE);
/* 创建myaddclass对象 */
myAdd = new myaddclass();
/* 计算并输出结果 */
result = myAdd.myadd(1, a, b);
System.out.print("\nThe sum of " + a.toString() + " and " + b.toString() + " is: ");
System.out.println(result[0]);
}
catch (Exception e)
{
System.out.println("Exception: " + e.toString());
}
finally
{
/* Free native resources */
MWArray.disposeArray(a);
MWArray.disposeArray(b);
MWArray.disposeArray(result);
if (myAdd != null)
myAdd.dispose();
}
}
}
9. 在Command Window中执行如下代码进行编译:
!javac MJBuilderTest.java
10. 编译通过后,执行如下代码:
!java MJBuilderTest 1 2
你将会看到如下结果:
The sum of 1 add 2 is: 3
前段时间摸索了java调用matlab东西,不说学的有多深,也算有结果了,达到目的了。也即用java程序可以调用matlab中函数了。
按顺序说吧,最开始肯定是下个matlab看看。下哪一个呢。开始下一个7.0觉得很新了。后来才觉得不是,现在都有7.8了。同时网上还流传着另外一种版本号信息,即2006版、 2006a版、2008b版,后来从网上找资料才知道,原来,matlab是一年两版的,叫a版和b 版。比如MATLAB 7.2 (Release 2006a),我下的是m7.8即2009a版。网上有对应关系,有兴趣可以找一下。
先说明一下,我用java调用matlab用的是matlab人提供的,MABLAB BUILDER JA工具,还要告诉你,这工具2006b版以前是没有的,我想以前java可能通过JNI通过c来调用matlab的。所以你下载时要注意版本了。还有一点要说明下,如果你用的是AMD的处理器,不是intel的处理器,安装matlab后,可能不能运行,具体表现是,一打开就关闭了。我公司机器用就是AMD的处理器,解决办法其实也很简单,就是给你的机器新建立一个系统变量,变量名是BLAS_VERSION,变量值是D://MATLAB7//bin//win32//atlas_Athlon.dll(你的matlab安装地址)。
然后,就是我们学着用MABLAB BUILDER JA了,开始不知道看matlab帮助,只是从网上看别人写的东西,关于这样的文章基本上出自一个娘胎,我不明白的地方,都一样的没有。后来看到了matlab帮助文档了,确实兴奋了一把,那才是最正宗的。下面我就试着按照它的说明一步一步说一下。
先来,介绍一下MATLAB® Builder™ JA吧,它是 MATLAB® Compiler™的扩展产品,用它你可以把你的m-code文件包装起来,并打包到一个多个class文件中,这样的你的java程序就能用matlab了,其实是这样的,m-codeiv当然就是你想调用的matlab程序了。
要说明一点,如果你只是在安装matlab的机器上,用java调用运行由MATLAB® Builder™ JA生成的jar包,当然可以。
如果你要在没有安装matlab的机器上用java调用这些jar包,怎么办?也是可以的,不过,不过你要先在机器上安装matlab提供的MATLAB Compiler Runtime (MCR),它的安装文件在C:/Program Files/MATLAB/R2009a/toolbox/compiler/deploy/win32下(你的安装目录下)文件名MCRInstaller.exe。
准备工作:
java环境,JAVA_HOME设置正确。还有一点你jdk版本要是1.6以上的,1.5可能有错。
关键部分来了,在这部分你可以,通过一个例子,看到一个M-code function转变成为java可调用组件。
这个例子的名字叫,magic square,这个例子让你学会如何,创建一个叫magicsquare 的java组件,它主要包括一个 magic class,和一个jar文件,还有其它上些发布组件用到的文件。magic .class是最关键的,就是它包装了, MATLAB 的函数 makesqr, makesqr函数是计算魔方数组用的,后面我们就是java程序,调用这个函数。
MATLAB Builder JA,可以通过在matlab命令,deploytool 调出,在这之间,为了验证matlab已能得到你的java环境了,你可以用,getenv JAVA_HOME来验证一下,能返回你的JAVA_HOME就是正确的了。
这个例子的,m代码和java代码,matlab都帮我们写好了。你现在需要做的就是把它的代码拷贝你的工作空间中,它是例子在
matlabroot /toolbox/javabuilder/Examples/MagicSquareExample .
matlabroot就是matlab的安装目录。
拷贝MagicSquareExample这个文件夹到你工作空间, for example, D:/javabuilder_examples
记得不要有空格。把MagicSquareExample子目录改名为 magic_square,现在的文件结构应该是D:/javabuilder_examples/magic_square .没错的话。然后把matlab工作空间转到D:/javabuilder_ examples/magic_square。 最后,要用m-code function我们要先测试它,打开makesqr.m文件,然后在matlab命令行中,输入 makesqr(5),看看结果是不是
17 24 1 8 15
deploytool 调出 MATLAB Builder JA,它应该是如下这个样子
然后你选择MATLAB BUILDER JA,新建一个工作,点击Browse按钮把你的工作放在
D:/javabuilder_examples/magic_square.输入magicsquare 作为工程名称。默认工程名字也是
D:/javabuilder_examples/magic_square目录下的包名。
MATLAB Builder JA 分配classes存放的文件夹名是按工程名称来设置的,所以在本工作中,Magicsquare 就是作为,calsses存放目录
名称了,我们要手动改它名字为,class,直接右击就可以改了。(这也是我以前看别人文章的,老找不到他们所谓的class文件夹的原因,也没人说这个问题)
工作建好以后,你可以setting你的工程,matlab的指南上说,让我们把Generate Verbose Output 选项选上,这样就能看到出错信息,实际上它默认是选择的。
然后,把m文件添加到工程中,在matalb中找到makesqr.m 文件把它,用鼠标拖到工程的magic文件夹下。然后保存工程。
下面就是构建工程,点击面板上方
按钮,等待一会,matlab就会你的工程目录下,创建src 和distrib两个文件夹。 src目录中包括有,生成的java文件,magic.class。distrib目录中包括有java存档文件,magicsquare.jar。
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
下面就是把m-code函数创建成一个java组件。用刚才说的,
接下来,就是验证你用matlab builder ja生成的java组件是不是能用的时候了。
先在你的java ide中建立一个java工程,然后把刚才生成的magicsquare.jar,还有,matlabroot/toolbox/javabuilder/jar/javabuilder.jar加入你的java工程构建路径中去。
然后你把D:/javabuilder_examples/magic_square/MagicDemoJavaApp下的getmagic.java测试文件拷贝到你java工程下,然后直接运行它。具体是怎么调用的,你看一测试代码就知道了,很easy.
就可以测试了。它是提示你输入一个数。如输入5,回车得到
Magic square of order 5
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
就正确了。