主要内容

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

部署从 MATLAB Handle 类继承的 MATLAB

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

数据 API:MATLAB® Data Array for .NET

此示例说明如何打包从 MATLAB 句柄类继承的 MATLAB 类并将其部署到 C# 应用程序。它使用 .NET 的 MATLAB Data API 来管理 MATLAB 代码和 C# 应用程序之间的数据交换。该工作流支持 Windows®、Linux®macOS

自 R2023b 起,带有包含 MATLABMATLAB 的 .NET 应用程序可以跨 Windows、Linux 和 macOS 平台开发和发布。这意味着可以在这三种平台中的任一平台上进行开发,然后发布到另外两个平台上。但是,自 R2024a 起才支持部署从 MATLAB 句柄类继承的 MATLAB 类。

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

前提条件

  • 创建一个对 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 句柄类的 MATLAB 类生成 .NET 程序集时,现在支持以下功能:

  • 复制行为:生成的 .NET 程序集复制了 MATLAB 句柄类复制行为。在 MATLAB 中,句柄对象是引用类型,这意味着当您复制这些对象时,原始变量和新变量都引用同一个对象。当您部署到 .NET 时,此行为现在保留在 C# 翻译中。

  • 关系运算符:.NET 程序集中基于 MATLAB 句柄类定义创建的 C# 对象支持关系运算。这允许在 C# 中使用标准关系运算符(==!=<><=>=),类似于它们在 MATLAB 中的功能。

  • isvalid 方法支持:.NET 程序集包括对 isvalid 方法的支持,与 MATLAB 句柄类行为一致。在 C# 中,此方法检查从 MATLAB 句柄类创建的对象是否仍然有效或已被删除,从而反映 MATLAB 中的功能。

  • delete 方法支持:对于从 MATLAB 句柄类派生的 C# 对象,.NET 程序集也支持 delete 方法。此函数可以以与 MATLAB 中处理删除的方式一致的方式删除这些对象。

创建从 MATLAB Handle 类继承的 MATLAB

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

classdef BankAccount < handle
    % BankAccount - A class for managing a bank account.
    %
    % This class provides methods to deposit, withdraw, and check the 
    % balance of a bank account.
    %
    % BankAccount Properties:
    %   Balance - The current balance of the account (private access).
    %
    % BankAccount Methods:
    %   BankAccount - Constructor, initializes account with a balance.
    %   deposit - Deposit money into the account.
    %   withdraw - Withdraw money from the account.
    %   checkBalance - Check the current balance of the account

    properties (Access = private)
        Balance (1,1) double {mustBeReal}
    end
    
    methods
        % Constructor to initialize the account with a balance
        function obj = BankAccount(initialBalance)
            arguments (Input)
                initialBalance (1,1) double {mustBeReal}
            end
            if nargin == 0
                initialBalance = 0;
            end
            obj.Balance = initialBalance;
        end
        
        % Method to deposit money
        function deposit(obj, amount)
            arguments (Input)
                obj (1,1) BankAccount
                amount (1,1) double {mustBeReal}
            end
            if amount > 0
                obj.Balance = obj.Balance + amount;
            else
                error('Amount must be positive');
            end
        end
        
        % Method to withdraw money
        function withdraw(obj, amount)
            arguments (Input)
                obj (1,1) BankAccount
                amount (1,1) double {mustBeReal}
            end
            if amount <= obj.Balance && amount > 0
                obj.Balance = obj.Balance - amount;
            else
                error('Insufficient funds or invalid amount');
            end
        end
        
        % Method to check the balance
        function bal = checkBalance(obj)
            arguments (Input)
                obj (1,1) BankAccount
            end
            arguments (Output)
                bal (1,1) double {mustBeReal}
            end
            bal = obj.Balance;
        end
    end
end

资深 MATLAB 用户可能会发现,在类中看到 properties 模块,在方法或函数中看到 arguments 模块,并且每个块都详细记录数据类型信息,这是很不寻常的。这两个模块都允许您使用等效的 MATLAB 类型表示 C# 数据类型。例如,如果您的 C# 应用程序采用 double 数据类型来表示一个值,那么您现在可以在 MATLAB 中将其表示为 double。您还可以将 MATLAB 对象指定为参量或属性类型。例如,checkBalance 方法指定 BankAccount 作为输入参量的类型,并指定 double 作为输出参量的类型。

在命令提示符下测试 MATLAB 类。

%% Create a new bank account with an initial balance of 100
account = BankAccount(100);

%% Deposit 50 into the account
account.deposit(50);
disp(['Balance after deposit: ', num2str(account.checkBalance())]);

%% Withdraw 30 from the account
account.withdraw(30);
disp(['Balance after withdrawal: ', num2str(account.checkBalance())]);

%% Create a joint account that references the same existing account
jointAccount = account;

%% Deposit 20 using the shared reference
jointAccount.deposit(20);
disp(['Balance from sharedAccount: ', num2str(jointAccount.checkBalance())]);
disp(['Balance from original account: ', num2str(account.checkBalance())]);

Balance after deposit: 150
Balance after withdrawal: 120
Balance from sharedAccount: 140
Balance from original account: 140

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

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

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

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

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

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

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

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

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

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

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

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

 BankAccount.cs

MATLAB 类与生成的 C# 类之间的映射

MATLAB 类元素C# 类元素a
BankAccount 类定义[MATLABClass("BankAccount")]
BankAccount 构造函数public BankAccount(MATLABProvider _matlab, double initialBalance)
deposit 方法public void deposit(double amount)
withdraw 方法public void withdraw(double amount)
checkBalance 方法

public void checkBalance()

public void checkBalance(out double bal)

从 MATLAB 句柄类继承的关系运算符

  • ==

  • !=

  • <

  • >

  • <=

  • >=

public static bool operator ==

public static bool operator !=

public static bool operator

public static bool operator >

public static bool operator <=

public static bool operator >=

从 MATLAB 句柄类继承的 delete 方法public void delete()
从 MATLAB 句柄类继承的 isvalid 方法public void isvalid(), public void isvalid(out dynamic validity)

a Input arguments are in C# data types corresponding to those defined in the MATLAB class' arguments block.

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 BankAccountConsoleApp

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

    • obj 文件夹

    • BankAccountConsoleApp.csproj 工程文件

    • Program.cs C# 源文件

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

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

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

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

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

      • MathWorks.MATLAB.Runtime.dll

      • MathWorks.MATLAB.Types.dll

       Windows 路径

       LinuxmacOS 路径

      注意

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

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

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

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

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

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

     BankAccountConsoleApp.csproj (Windows)

     BankAccountConsoleApp.csproj (Linux)

     BankAccountConsoleApp.csproj (macOS)

    注意

    如果您选择在 C# 代码文件上使用由 compiler.build.dotNETAssembly 生成的 Banking.dll .NET 程序集,请记住取消注释工程文件中对 Banking.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

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

    dotnet build BankAccountConsoleApp.csproj

运行 C# 应用程序

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

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

!dotnet run

应用程序显示平均值。

Balance after deposit:  150
Balance after withdrawal:  120
Balance from joint account:  140
Balance original account:  140

注意

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

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

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

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

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

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

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

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

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

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

    • MathWorks.MATLAB.Runtime.dll

    • MathWorks.MATLAB.Types.dll

     程序集依赖项的位置

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

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

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

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

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

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

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

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

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

    Balance after deposit:  150
    Balance after withdrawal:  120
    Balance from joint account:  140
    Balance original account:  140

    提示

    • 如果您无法构建应用程序,请将解决方案平台从 Any CPU 更改为 x64

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

另请参阅

| |

主题