主要内容

本页采用了机器翻译。点击此处可查看最新英文版本。

使用 MATLAB Data API for .NET 将 MATLAB 函数部署到 .NET 应用程序

支持的 .NET 版本:.NET 6.0 或更高版本

此示例说明如何打包 MATLAB® 函数并将其与用 C# 编写的 .NET 应用程序一起部署。Windows®、Linux®macOS 系统支持此工作流。本示例使用基于 Windows 工作流。

自 R2023a 起,可以跨 Windows、Linux 和 macOS 平台开发和发布包含打包的 MATLAB 代码的 .NET 应用程序。这意味着可以在这三种平台中的任一平台上进行开发,然后发布到另外两个平台上。在此版本之前,.NET 应用程序只能从 Windows 发布到 Linux 和 macOS

请注意,虽然开发和发布可以在任何平台上进行,但仍可能存在特定于平台的细微差别和问题。某些库或函数在不同平台上的行为可能会有所不同,开发人员应在目标平台上彻底测试他们的应用程序以确保预期的行为。

前提条件

  • 创建一个对 MATLAB 搜索路径可见的新工作文件夹。此示例使用名为 work 的文件夹。

  • 验证您是否已设置 .NET 开发环境。有关详细信息,请参阅设置 .NET 开发环境

  • 验证您是否已满足所有 MATLAB .NET 目标要求。有关详细信息,请参阅MATLAB Compiler SDK .NET 目标要求

  • 最终用户必须安装 MATLAB Runtime 才能运行应用程序。有关详细信息,请参阅下载并安装 MATLAB Runtime

    出于测试目的,您可以使用安装的 MATLAB 来代替 MATLAB Runtime

  • 验证您是否已安装 .NET 6.0 SDK 或更高版本或 Microsoft® Visual Studio® 2022(v17.0 或更高版本)。您可以在系统命令提示符下输入 dotnet --info 来验证 .NET 6.0 是否已安装。您可以从 https://dotnet.microsoft.com/download 下载特定于您的操作系统的 .NET SDK 版本。

数据管理

要在部署的 MATLAB 代码和 .NET 应用程序之间交换数据,请使用适用于 .NET 的 MATLAB Data API。MATLAB 引擎也使用此 API。有关概述,请参阅从 .NET 调用 MATLAB。有关详细信息,请参阅:

创建 MATLAB 函数

使用以下代码创建一个名为 calculateDistance.m 的 MATLAB 文件:

function distance = calculateDistance(p1, p2)
    % This function calculates the Euclidean distance between two points
    % Inputs:
    %   p1 - a two-element vector [x, y]
    %   p2 - a two-element vector [x, y]
    % Output:
    %   distance - the Euclidean distance between p1 and p2
    
    % Use arguments block to map C# type to corresponding MATLAB type
    % Int64[] <--> (1,2) int64 {mustBeReal}
    
    arguments (Input)
        p1 (1,2) int64 {mustBeReal}
        p2 (1,2) int64 {mustBeReal}
    end

    arguments (Output)
        distance (1,1) int64 {mustBeReal}
    end
    
    % Calculte Euclidean distance
    diff = p1 - p2;
    diffSq = diff.^2;
    sumSq = sum(diffSq);
    distance = sqrt(sumSq);
end

资深 MATLAB 用户可能会发现 arguments 模块的存在不太寻常。arguments 模块允许您用等效的 MATLAB 类型表示 C# 数据类型。例如,如果您的 C# 应用程序采用 Int64 数据类型来表示一个值,那么您现在可以在 MATLAB 中将其表示为 int64。当 C# 应用程序具有严格的类型要求时,此选项很有用。有关详细信息,请参阅Data Type Mappings Between .NET and Strongly Typed MATLAB Code

在这个示例中,具有指定类型信息的 arguments 模块用于阐明细微的差别。但是,请记住,合并 arguments 模块完全是可选的。即使没有它,部署过程仍然保持不变。这个示例的各个部分强调了这种差异的体现方面。因此,如果数据类型不是很重要,则不需要使用 arguments 模块来指定类型信息。

在命令提示符下测试 MATLAB 函数。

p1 = int64([0, 0])
p2 = int64([3 4])
distance = calculateDistance(p1,p2)
p1 =
  1×2 int64 row vector
   0   0
p2 =
  1×2 int64 row vector
   3   4
distance =
  int64
   5

使用 compiler.build.dotNETAssembly 创建 .NET 程序集

使用 compiler.build.dotNETAssembly 函数从 MATLAB 函数创建代码存档(.ctf 文件)。

buildResults = compiler.build.dotNETAssembly("calculateDistance.m", Interface="matlab-data",...
    Verbose="on", OutputDir=".\output", AssemblyName="CalculateDistance")

尽管通过 AssemblyName 属性提供程序集名称不是强制性的,但强烈建议这样做。这样做会为生成的 .NET 程序集和 C# 文件提供更清晰的命名空间。如果没有它,名为 example 的根命名空间会自动追加到子命名空间,从而导致命名空间结构混乱且可能令人困惑。

该函数生成一套文件(如下所列),并将它们放在指定的 output 目录中。其中,集成过程中使用的关键文件是包含 MATLAB 代码的代码存档(.ctf 文件)、C# (.cs) 代码文件和 .NET 程序集(.dll 文件)。有关其他文件的信息,请参阅打包 MATLAB 函数后生成的文件

P:\MATLAB\WORK\OUTPUT
│   CalculateDistance.csproj
│   CalculateDistance.ctf
│   CalculateDistance.deps.json
│   CalculateDistance.dll
│   GettingStarted.html
│   includedSupportPackages.txt
│   mccExcludedFiles.log
│   readme.txt
│   requiredMCRProducts.txt
│   unresolvedSymbols.txt
│
└───strongly_typed_interface
        calculateDistance.cs

要完成集成,您可以选择以下两个选项之一:

  • CalculateDistance.ctf 代码存档文件与 calculateDistance.cs C# 代码文件结合使用。

  • CalculateDistance.ctf 代码存档文件与 CalculateDistance.dll .NET 程序集文件结合使用。

经检查,您会注意到该函数还生成一个 CalculateDistance.csproj 工程文件。该文件是专门为创建相应的 CalculateDistance.dll .NET 程序集文件而生成的。但是,它不应被误认为是 .NET 工程的模板,并且不得在该环境中使用。

此示例采用第一个集成选项来说明类型映射机制。在工作流的相关阶段插入了使用第二种选项的相关指导。

您可以检查以下 C# 代码文件的内容:

 calculateDistance.cs

calculateDistance.cs C# 代码文件中,MATLAB 函数的 int64 参量规范反映了其 C# 等效项 Int64

    arguments (Input)
        p1 (1,2) int64 {mustBeReal}
        p2 (1,2) int64 {mustBeReal}
    end
   
Int64[] p1, 
Int64[] p2 )
    arguments (Output)
        distance (1,1) int64 {mustBeReal}
    end
public static void calculateDistance(
            MATLABProvider _matlab, Int64[] p1, Int64[] p2, out Int64 distance)
        {
            dynamic _dynMatlab = _matlab;
            distance = (Int64)_dynMatlab.calculateDistance(
                new RunOptions(nargout: 1), p1, p2);
        }

当您的 MATLAB 函数中没有包含详细说明类型信息的 arguments 模块时,就会生成以下 C# 代码文件:

 calculateDistance.cs(与类型无关)

C# 代码文件之间的主要区别在于输入和输出变量的类型规范。当使用指定类型信息作为 arguments 模块时,输入和输出将被归类为 Int64。相反,当不存在具有类型信息的 arguments 模块时:

  • C# 方法的输入必须是 MATLAB 函数可以处理的类型。它们在 C# 代码文件中表示为具有 dynamic 类型。有关映射的详细信息,请参阅Pass .NET Data Types to MATLAB Functions

  • 在 C# 代码文件中,MATLAB 函数的输出将转换为 MATLABArrayMATLABObjectMATLABStruct 等类型,具体取决于函数的返回值。然后必须将它们分配给相应的 C# 类型。如果使用不正确的类型,则会引发 System.InvalidCastException。有关映射的详细信息,请参阅Handle MATLAB Data in .NET Applications

指定输入和输出类型的过程通常涉及大量的参考和有根据的猜测。因此,使用包含类型信息的参量模块可以消除这种歧义,从而简化包含打包的 MATLAB 函数的 C# 应用程序的开发。

注意

生成的组件不包括 MATLAB Runtime 或安装程序。要使用 buildResults 对象创建安装程序,请参阅 compiler.package.installer

MATLAB 代码集成到 .NET 应用程序中

您可以在首选的 C# 开发环境中完成集成过程,包括文本编辑器以及 .NET SDK 命令行 API,或者 Windows 和 Microsoft macOS 上的 Visual Studio 等替代方案。此示例向您说明如何使用两个选项完成集成。有关详细信息,请参阅设置 .NET 开发环境

使用 .NET SDK 命令行 API 构建应用程序

如果您使用的是 Microsoft Visual Studio,请参阅使用 Microsoft Visual Studio 构建应用程序 (Windows)

  1. 在 Windows 中打开命令提示符并导航到本示例中使用的 work 文件夹。

  2. 在命令行中输入:

    dotnet new console --framework net6.0 --name DistanceConsoleApp

    此命令创建一个名为 DistanceConsoleApp 的文件夹,其中包含以下内容:

    • obj 文件夹

    • DistanceConsoleApp.csproj 工程文件

    • Program.cs C# 源文件

  3. 将由 compiler.build.dotNETAssembly 函数生成的以下文件与 dotnet new C# 应用程序代码文件一起复制到 Program.cs 创建的工程文件夹中:

    • 来自 .cs 目录的 ...\work\output\strongly_typed_interface\ C# 包装器文件。

    • 来自 ...\work\output 目录的代码存档 CalculateDistance.ctf

  4. 编辑工程以添加程序集依赖项和由 compiler.build.dotNETAssembly 函数生成的 CalculateDistance.ctf 代码存档文件。

    1. 在文本编辑器中打开工程文件,并使用以下程序集包含 <Reference> 标记内的 <ItemGroup> 工程标记:

      • MathWorks.MATLAB.Runtime.dll

      • MathWorks.MATLAB.Types.dll

       Windows 路径

       LinuxmacOS 路径

      注意

      如果您使用由 compiler.build.dotNETAssembly 函数生成的 CalculateDistance.dll .NET 程序集而不是 C# 代码文件,请将其作为引用包含在同一个 <ItemGroup> 标记。

    2. CalculateDistance.ctf 代码存档文件作为内容文件包含到工程中。

      • CalculateDistance.ctf 代码存档文件作为内容文件添加进 <ItemGroup> 标记。

      • 添加标记 CopyToOutputDirectory 并将其设置为 Always。此步骤确保在构建过程中将 CalculateDistance.ctf 文件复制到输出文件夹。这意味着当您构建工程时,该文件与您构建的 .exe 文件位于同一目录中。

      • 添加标记 CopyToPublishDirectory 并将其设置为 Always。此步骤确保将 CalculateDistance.ctf 文件复制到此工程发布到的跨平台文件夹中。

    一旦添加了程序集依赖项并将 CalculateDistance.ctf 作为内容文件包含进来,您的工程文件将如下所示:

     DistanceConsoleApp.csproj (Windows)

     DistanceConsoleApp.csproj (Linux)

     DistanceConsoleApp.csproj (macOS)

    注意

    如果您选择在 C# 代码文件上使用由 compiler.build.dotNETAssembly 生成的 CalculateDistance.dll .NET 程序集,请记住取消注释工程文件中对 CalculateDistance.dll 的引用标记。此更改可确保您的工程正确使用 .dll 文件。

  5. Program.cs C# 文件中的代码替换为以下代码:

     Program.cs

    注意

    macOS 系统上开发和操作时,将代码从 Main 方法转换到名为 MainFunc 的新函数。随后,从 MATLABRuntime.SetupMacRunLoopAndRun 方法中调用 Main,并将 MainFunc 与命令行参量一起作为参数传递。MATLABRuntime.SetupMacRunLoopAndRun 对于 macOS 环境来说是不可或缺 MATLABRuntime.SetupMacRunLoopAndRun,因为它允许 MATLAB 与 Core Foundation Run Loop (CFRunLoop) 交互,这是一种特定于 macOS 的机制,用于处理用户输入或计时器事件等事件。有关详细信息,请参阅 MathWorks.MATLAB.Runtime.MATLABRuntime

    当您的 MATLAB 函数中不包含详细说明类型信息的 arguments 模块时,您的 C# 应用程序代码必须按如下方式编写:

     Program.cs(与类型无关)

    在 C# 应用程序代码中,当没有详细说明类型信息的 arguments 模块时,您会发现输入通常指定为 double。虽然这不是默认设置,但它是一个实用的选择,因为 MATLAB 中的默认数据类型是 double。但是,值得注意的是,如果 MATLAB 函数可以处理这些输入类型,那么其他类型(例如 Int64Int32 也可能适合,具体取决于应用程序的具体要求。输出变量 distance 设置为 dynamic 类型。这种适应性类型旨在继承 MATLABArray 的类型,因为它是 MATLAB 函数的返回类型。完成此项任务后,distance 将被转换为 C#double,以便在程序中使用。

    使用 arguments 模块在 MATLAB 函数中加入显式类型信息有助于消除对数据类型的假设。这种做法不仅提高了清晰度,而且还通过减少潜在的类型不匹配错误增强了代码的稳健性。

  6. 在命令行中,输入以下命令来构建您的工程:

    dotnet build DistanceConsoleApp.csproj

运行 C# 应用程序

为了测试目的,您可以从 MATLAB 命令提示符运行该应用程序。这不需要安装 MATLAB Runtime

在 MATLAB 命令提示符下,导航到包含可执行文件的目录,然后输入以下内容运行您的应用程序:

!dotnet run

该应用程序显示两点之间的欧几里得距离。

Euclidean distance between [0, 0] and [3, 4] is: 5

注意

当您准备部署此应用程序时,请确保目标系统已安装 MATLAB Runtime。有关详细信息,请参阅下载并安装 MATLAB Runtime。在 Linux 和 macOS 系统上,必须在运行应用程序之前分别设置 LD_LIBRARY_PATHDYLD_LIBRARY_PATH 运行时路径。有关详细信息,请参阅针对部署设置 MATLAB Runtime 路径

使用 Microsoft Visual Studio 构建应用程序 (Windows)

  1. 打开 Microsoft Visual Studio 并创建一个名为 DistanceConsoleApp 的 C# Console App

  2. 选择 .NET 6.0 (Long-term support) 作为框架。

  3. Program.cs 文件中默认生成的源代码替换为此示例页面中的 Program.cs 文件中提供的特定源代码。

  4. 选择以下两个选项之一:

    • 要合并由 compiler.build.dotNETAssembly 函数生成的 calculateDistance.cs C# 代码文件,请导航到 Solution Explorer,右键点击您的工程,然后选择 Add > Existing Item。使用对话框查找并添加 calculateDistance.cs C# 代码文件。

    • 如果您更喜欢使用由 compiler.build.dotNETAssembly 函数生成的 CalculateDistance.dll .NET 程序集,请在 Solution Explorer 中右键点击您的解决方案,然后选择 Edit Project File。在这里,您需要在现有文件中添加对 CalculateDistance.dll 文件的引用 <ItemGroup> 标记。

    查看上面列出的工程文件之一作为参考。

  5. 添加以下程序集依赖项:

    • MathWorks.MATLAB.Runtime.dll

    • MathWorks.MATLAB.Types.dll

     程序集依赖项的位置

  6. CalculateDistance.ctf 代码存档文件作为内容文件添加到工程中。在 Solution Explorer 中右键点击您的工程,然后选择 Add > Existing Item。在对话框中,浏览文件并添加文件。

  7. Solution Explorer 中右键点击 CalculateDistance.ctf 文件并选择 Properties。在 Properties 窗口中,将 Build Action 设置为 Content,并将 Copy to Output Directory 设置为 Copy always

  8. Solution Explorer 中右键点击您的工程并选择 Edit Project FileDistanceConsoleApp.csproj 工程文件在编辑器中打开。添加 <CopyToPublishDirectory> 标记正下方 <CopyToOutputDirectory> 标记并将其设置为 AlwaysDistanceConsoleApp.csproj 工程文件的已编辑部分如下所示:

    ...
    <ItemGroup>
        <Content Include="CalculateDistance.ctf">
          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
          <CopyToPublishDirectory>Always</CopyToPublishDirectory>
        </Content>
    </ItemGroup>
    ...

  9. 在菜单栏上,选择 Build,然后选择 Build Solution 以在 Visual Studio 中构建应用程序。

    编译过程会生成一个名为 DistanceConsoleApp.exe 的可执行文件。

  10. Ctrl+F5 从 Visual Studio 运行应用程序。或者,您可以从系统终端执行生成的可执行文件:

    > cd C:\work\DistanceConsoleApp\DistanceConsoleApp\bin\Debug\net6.0
    > DistanceConsoleApp.exe

    应用程序会返回与 MATLAB 示例代码相同的输出。

    Euclidean distance between [0, 0] and [3, 4] is: 5

    提示

    如果您无法从 Visual Studio 运行应用程序,请打开 Developer Command Prompt for Visual Studio,然后输入 devenv /useenv 启动 Visual Studio。然后,打开您的工程并运行您的应用程序。

发布到 LinuxmacOS

注意

在 R2023a 之前的版本中: 应用程序只能从 Windows 发布到 Linux 和 macOS

  • 要将应用程序发布到 Linux,请在系统命令提示符下输入以下命令:

    dotnet publish --configuration Release --framework net6.0 
      --runtime linux-x64 --self-contained true DistanceConsoleApp.csproj

  • 要将应用程序发布到 macOS,请在一行中输入以下命令:

    dotnet publish --configuration Release --framework net6.0 
      --runtime osx.12-x64 --self-contained true DistanceConsoleApp.csproj

要发布到特定平台,请使用适当的运行时标识符 (RID)。有关详细信息,请参阅 https://learn.microsoft.com/en-us/dotnet/core/rid-catalog

Visual Studio 发布

有关如何从 Visual Studio 设置发布的详细信息,请参阅 .NET 文档。设置完成后,编辑您的发布配置文件以包含以下设置:

  • Configuration 设置为 Release | Any CPU

  • Target framework 设置为 net6.0

  • Deployment mode 设置为 Self-contained

  • Target runtime 设置为 linux-x64osx-x64

  • 保持 Target location 不变或将其设置为您选择的位置。

Linux 上运行已发布的应用程序

  1. Release 文件夹从 Windows 上的 C:\work\DistanceConsoleApp\bin 复制到 Linux 计算机上的 ~/work。如果尚不存在 work 文件夹,请在 Linux 上创建一个。

  2. 在 Linux 计算机上,验证您是否已安装 MATLAB Runtime 并设置了 LD_LIBRARY_PATH 环境变量。有关详细信息,请参阅下载并安装 MATLAB Runtime针对部署设置 MATLAB Runtime 路径

  3. 打开 Linux 控制台并导航至:

    ~/work/Release/net6.0/linux-x64/publish
  4. 为 Linux 可执行文件添加执行权限:

    chmod +x DistanceConsoleApp

  5. 输入以下命令运行应用程序:

    ./DistanceConsoleApp
    Euclidean distance between [0, 0] and [3, 4] is: 5

按照类似的步骤在 macOS 上运行该应用程序。

注意

您可以使用 .NET Framework 4.6.1 或更高版本来实现此示例。但是,您无法跨平台部署该示例。此外,.NET Framework 没有命令行界面。

另请参阅

| |

主题

外部网站