MATLAB 编译为Java Package

本文介绍了如何将MATLAB脚本编译为Java Package,详细阐述了脚本编写、打包过程,以及在Java中调用MATLAB函数的方法,包括输入、输出处理。同时,讲解了在Windows和Ubuntu上的环境部署,特别提到了MATLAB Compiler Runtime (MCR) 的安装和配置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

相比java等语言,MATLAB在矩阵计算等方面可太强大了。要是java能直接调MATLAB就好了。

确实可以!机缘巧合之下,发现了这个思路,折腾了好几天。

(有些不足的就是其调用开销比较大,目前还不知道如何合理的调用,)

后面了解到,一个处理方法是,先将matlab转为C,再转为Java,这样可以避免java在每次调用函数时需要与Matlab环境进行通讯导致效率低下的问题。(也许不能算通讯,数据交换?)——2022/03/20

MATLAB 编译

脚本编写

编写一个MATLAB函数脚本,这里我以绘图函数为例。

% 自定义画图函数drawplot.m
% 以两个1*n的矩阵为x,y坐标绘制一段线
% 参数 x y  
function drawplot(x, y)    
plot(x, y, 'r'); %%使用matlab函数plot()作图      
xlabel('X轴')  
ylabel('Y轴') 
end

另外还有一个drawplot2Line.m用于输出两条线(红+蓝)

打包

  1. 在MATLAB命令行窗口输入deploytool,打开部署工具
    MATLAB Compiler窗口1

  2. 选择 Library Compiler

  3. 添加脚本并配置
    MATLAB Compiler 窗口2

    1. 选择导出类型(我选择Java Package)
    2. 选择要转换的脚本文件(可导入多个)
    3. 导出的包名
    4. 在jar包中要生成的类以及类内方法(类名可自定义)
    5. 是否一起打包MATLAB运行环境MCR(默认不打包,自行从网上下载)
    6. 打包
  4. 等待打包完成

  5. 生成的共有三个文件夹,其中包含导出的jar包和javadoc文档

    • for_redistribution
    • for_redistribution_files_only
    • for_testing

    (三者有什么区别我也没有理解透,只要知道取出其中的包导入到java工程中就好)

Java调用

需要将上述方法导出的jar包以及MATLAB安装目录下的\toolbox\javabuilder\jar\javabuilder.jar包一同导入到Java工程中。Java导入本地jar包我这里就不讲了。

对于矩阵数据,需要使用javabuilder.jar中提供的MWNumericArray进行传参。

输入

传递给MATLAB函数时,基本类型可以直接带入,矩阵需要使用MWNumericArray

常规的矩阵输入方式:

MWNumericArray input = null; // 用于保存输入矩阵
//方式一:
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);

调用

Class1 c1=null;
try{
    //输入参数配置
    ...
    c1 = new Class1();
    c1.draw.plot(x,y); //无返回
    output = c1.myFunction(1, intput); //有返回(返回一个参数Object[1])
    output2 = c1.myFunction2(3, intput); //有返回(返回三个参数Object[3])
    //处理返回值
    ...
}catch(Exception e){
    System.out.println(e);
}finally{
    //释放资源
    ...
}

对于导出的函数,其结构有两种:

  1. 对于无数据输出的,为function(Onject... obj),直接输入参数即可;
  2. 对于有数据输出的,为function(int i, Object... obj)i表示返回的参数个数,Object... obj为对应MATLAB函数所输入的参数。

输出

对于有数据返回的函数,返回值为Objecct[]数组。

处理方式:

MWNumericArray output = null;  //用于保存输出矩阵
output=(MWNumericArray) result[0]; //将结果Object[]转换成MWNumericArray
double res = output.getDouble(1); //从MWNumericArray对象中读取数据

其他的读取数据方式见【4. MWNumericArray方法】

后期处理

释放本地资源

MWArray.disposeArray(input);  //建立的矩阵用这句
WArray.disposeArray(output);  // 建立的矩阵用这句
MWArray.disposeArray(result);  //建立的Object数组用这句
c1.dispose();  //建立的matlab类对象用这句
//以上释放时,必须保证其不为null。

MWNumericArray方法

  • getDouble():以double格式从MWNumericArray获取矩阵第一个数,常用于只有一个数的矩阵
  • getDouble(int i):以double格式从MWNumericArray获取矩阵第i个数
  • getDouble(int[] i):以double的格式从MWNumericArray获取矩阵中的i[0]行,i[1]列的数(多维则i有多个元素)
  • getDoubleData():以double[]一维数组的格式从MWNumericArray获取矩阵(按列连接)
  • toDoubleArray():将矩阵以Object返回,实为多维double数组返回,需要强制转换成为多维数组。
  • set(int[] i, double):对矩阵的i[0]i[1]列进行赋值

其他如getByte, getInt, getShort, getLong, getFloat也是同样的用法。

示例

这里我以调用drawplot2Line()作为例子。

MWNumericArray x = null;
MWNumericArray y = null;
Plotter plotter = null;
try {
    int[] dims = {1, 120001};
    x = MWNumericArray.newInstance(dims, MWClassID.DOUBLE);
    y = MWNumericArray.newInstance(dims, MWClassID.DOUBLE);
    for (int i = 1; i <= 120001; i++) {
        double t=0.001*i-6;
        x.set(i, 16*Math.pow(Math.sin(t),3)
        y.set(i, 13*Math.cos(t)-5*Math.cos(
    }
    plotter = new Plotter();
    plotter.drawplot( x, y);
    plotter.waitForFigures();
} catch (Exception e) {
    System.out.println(e);
} finally {
    // 释放本地资源
    MWArray.disposeArray(x);
    MWArray.disposeArray(y);
    if (plotter != null) {
        plotter.dispose();
        System.out.println("over");
    }
}

绘制爱心

这里我是用了比较简单的函数来画的爱心

x=16*(sin(t))^3y=13*cos(t)-5*cos(2*t)-2*cos(3*t)-cos(4*t),其中-6<=t<=6

当然也可以采用其他的图形。

环境部署

一般而言,在运行环境下是没有MATLAB的。

没有MATLAB环境下调用jar包,会由于MWNumericArray这些类出现NoClassDefFoundError问题。对这一问题在【怎么解决java.lang.NoClassDefFoundError错误】中有很好的解释

但MATLAB又太大,10+G起步,更好的办法就是安装MATLAB Compiler Runtime (MCR) ,虽说对于我的R2018a(9.4)版本的MCR也有1G+大了。

安装的MCR需要与编译时使用的MATLAB版本一致,我自己使用的是R2018(9.4)

Windows

下载后双击安装即可

Ubuntu

下载

wget https://ssd.mathworks.com/supportfiles/downloads/R2018a/deployment_files/R2018a/installers/glnxa64/MCR_R2018a_glnxa64_installer.zip

解压

unzip MCR_R2018a_glnxa64_installer.zip

安装

默认在 /usr/local/MATLAB/MATLAB_Runtime/v94

注意这里最后的版本号要视自己情况

# 普通安装
sudo -H ./install
# 静默安装(无UI的Ubuntu下)
sudo ./install -mode silent -agreeToLicense yes
# 指定目录
sudo ./install -mode silent -agreeToLicense yes -destinationFolder  /data/tomcat/MCR

环境配置

虽说按照官方的走了一遍,但并没有成功,后面尝试了写到/etc/profile中也还是不行,待有空了继续捣鼓吧。 比较毕竟ubuntu只是尝试着用一用,主力还是在windows上,而且Windows安装MCR会自动配置好环境。

  1. 查看当前的SHELL环境

    echo $SHELL
    
  2. 根据不同的SHELL环境选择不同的配置方法(我的环境为/bin/bash

  3. 保存当前的库路径为mypath变量,并输出

    mypath=$LD_LIBRARY_PATH && echo $mypath
    
  4. 附加MATLAB环境到mypath中。

    mypath="${mypath:+${mypath}:}
    <MATLAB_RUNTIME_INSTALL_DIR>/runtime/glnxa64:
    <MATLAB_RUNTIME_INSTALL_DIR>/bin/glnxa64:
    <MATLAB_RUNTIME_INSTALL_DIR>/sys/os/glnxa64:
    <MATLAB_RUNTIME_INSTALL_DIR>/extern/bin/glnxa64"
    

    以上命令需要在一行中输入,如:

    mypath="${mypath:+${mypath}:}/usr/local/MATLAB/MATLAB_Runtime/v94/runtime/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v94/bin/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v94/sys/os/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v94/extern/bin/glnxa64"
    
  5. 再次打印输出查看mypath

    echo $mypath
    
  6. 在当前会话中将mypath赋给LD_LIBRARY_PATH

    注意!永久修改会影响原系统对 lib 动态链接库的调用,比如说后来我在使用vim时会因为libexpat.so.1被定位到MATLAB中的,导致原来的vim无法使用(我印象里似乎我的初始LD_LIBRARY_PATH是为空?按理说我写的mypath是基于LD_LIBRARY_PATH附加的,但后来看只有新加的MATLAB相关的了)

    从网上找了一份原版的

    export LD_LIBRARY_PATH=/lib:$HOME/lib:/lib/x86_64-linux-gnu:/usr/lib
    echo "export LD_LIBRARY_PATH=$LD_LIBRARY_PATH" >> ~/.bashrc
    
    export LD_LIBRARY_PATH=$mypath
    
  7. 如永久设置则需要执行以下命令,写到~/.bashrc

    echo "export LD_LIBRARY_PATH=$mypath" >> ~/.bashrc
    
  8. 应用更改

    source ~/.bashrc
    
  9. 检查GNU版本

ldd --version

如果是2.17及以下,则还需要按上述步骤将<MATLAB_RUNTIME_INSTALL_DIR>/bin/glnxa64/glibc-2.17_shim.so添加到LD_PRELOAD环境变量中。

卸载

rm -rf <MATLAB_RUNTIME_INSTALL_DIR>
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值