MATLAB函数外部使用

Tim 26 2025-03-07

项目需要在C#中使用MATLAB函数,根据网上老哥提供的方案查阅资料并记录以下(有部分可能存在认知错误,后面遇到再改)

ArrayFire/ Armadillo

未尝试

C++库,对MATLAB函数进行逐句翻译,直接编译成dll。 效率最高(需要硬件支持)

ArrayFire

ArrayFire是一个通用的GPU计算库,旨在简化并行架构(如CPU、GPU和其他硬件加速设备)上的软件开发过程。该项目主要使用C++编写,但也提供了其他语言的API,如C、Python和Fortran,以满足不同开发者的需求。 官方网站

Octave/Python

转Octave或者Python。 工作量最小,效率还行

Octave

下载地址

mkoctfile

未尝试

入参是 矩阵/张量,使用mkoctfile编译dll方便点

mkoctfile --link-stand-alone

Octave.NET

.NET拓展包。 仓库地址

Basics

基础使用:

//指定octave-cli.exe路径(可选) 
OctaveContext.OctaveSettings = new OctaveSettings() { OctaveCliPath = @"D:\GNU Octave\Octave-9.4.0\mingw64\bin\octave-cli.exe" };
 using (var octave = new OctaveContext())
 {
     // Please note that there is no ";" at the end. This is important if we want to capture the output.
     var scalarResult = octave
             .Execute("2 + 2")
             .AsScalar();

     var vectorResult = octave
         .Execute("[1 2 3 4 5]")
         .AsVector();

     var matrixResult = octave
         .Execute("[1 2 3 4 5; 5 4 3 2 1]")
         .AsMatrix();

     var vec = new double[] { 1, 2, 3, 4, 5 };
     var anotherVector = octave.Execute(vec.ToOctave()); // [1 2 3 4 5]

     var mat = new[]
     {
         new double[] { 1, 2, 3, 4, 5 },
         new double[] { 1, 2, 3, 4, 5 }
     };
     var anotherMatrix = octave.Execute(mat.ToOctave());// [1 2 3 4 5;1 2 3 4 5]
 }
DisplayPlot

显示图表:

using (var octave = new OctaveContext())
{
                // Note: your octave-cli must support some plot backend, in case of problems investigate manually in octave-cli

                var script = @"
x = -10:0.1:10;
y = sin (x);

handle = plot (x, y);

title (""Hello from C#"");
xlabel (""x"");
ylabel (""sin (x)"");

waitfor(handle); #                 <- without that plot window would not show 
                ";

                octave.Execute(script, int.MaxValue);
}
Packages

加载包:

using (var octave = new OctaveContext())
{
    octave.Execute("pkg load fuzzy-logic-toolkit;");
    double result = octave
        .Execute("algebraic_product(5,2)")
        .AsScalar(); // 10
}
引用外部.m文件

需要注意的是调用函数时结尾不要加分号octave.Execute("t1(6, 7)") 否则就抑制输出了,得用 disp() 显示

addpath 指定工作区:

//指定octave-cli.exe路径(可选) 
OctaveContext.OctaveSettings = new OctaveSettings() { OctaveCliPath = @"D:\GNU Octave\Octave-9.4.0\mingw64\bin\octave-cli.exe" };
 using (var octave = new OctaveContext())
 {
     string script = @"addpath('C:/Users/admin/Desktop/test');t1(6, 7)";

      // 调用 Octave 函数
      var sumResult = octave.Execute(script); 
 }
直接运算

在C#中运行Octave 代码:

//指定octave-cli.exe路径(可选) 
OctaveContext.OctaveSettings = new OctaveSettings() { OctaveCliPath = @"D:\GNU Octave\Octave-9.4.0\mingw64\bin\octave-cli.exe" };
 using (var octave = new OctaveContext())
 {
                    string funcDef = @" wt=[0.123456 1.234567 0.345678];  ...
    i = 1; ...
    outputs = {}; ...
    predict = zeros(1, 3); ...
    for k = 1:length(wt) ...
        outputs{i, k} = round(wt(k)); ...
        predict(i, k) = round(wt(k)); ...
    end ...
  
";
                    octave.Execute(funcDef);

                    var r1 = octave.Execute("disp(cell2mat(outputs))");
                    var r2 = octave.Execute("disp(predict)");

                    var result1 = r1.AsMatrix();
                    var result2 = r2.AsVector();
 }

MATLAB Compiler

直接编译为dll或者exe,需要依赖MCR(MATLAB Compiler Runtime)且调用dll之前要启动一个ngine 之类的东西。影响效率

.NET Assembly

打包 MATLAB函数

MATLAB中选APP菜单 找到库编译器 Library Compiler

  1. Type:选择目标类型 (这里选.NET Assembly

  2. Exported Functions:添加需要打包的函数文件

  3. Library information:重命名库名称,重命名类名称,或者添加类,分配函数所属类

  4. Package:打包

C#调用

打包好的dll在for_redistribution_files_only目录下,里面两个dll都可以使用

除了需要引用打包好的dll,还需要引用 MWArray.dll该文件在Matlab安装目录中,参考路径: 安装路径\MATLAB\R2023a\toolbox\dotnetbuilder\bin\win64\v4.0\

直接实例打包时设置的类名即可:

//添加引用
using System;
using TESTNative;
using MathWorks.MATLAB.NET.Arrays; 

//触发代码
private void TEST_Click(object sender, EventArgs e)
        {
            int[,] list = { { 1 }, { 2 }, { 3 }, { 4 } }; //列向量
            MWArray array = new MWNumericArray(list); //转换list格式

            TESTNative.Cal ts = new Cal();//定义目标类
            object resultObj = ts.TEST(1, array);// 1表示返回的结果数量,要小于等于Matlab对应函数实际的返回值数量
            //转换返回值
            object[] resultObjs = (object[])resultObj;
            double[,] calcResult = (double[,])resultObjs[0];
        }

参考

https://blog.csdn.net/qq_45389511/article/details/137199865