主要内容

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

将 .NET 对象传递给 MATLAB 函数

此示例说明如何将 .NET 对象传递给 C# 应用程序中部署的 MATLAB 函数。该工作流支持 Windows®、Linux®macOS 系统。

从 R2024b 开始,MATLAB®macOS 系统支持将 .NET 对象传递给 Linux 函数。在此版本之前,它仅支持 Windows 系统。如果您在 Windows 上遇到任何问题,请将环境变量 USE_DOTNETCLI2_WINDOWS 设置为 1 (自 R2024b 起)

前提条件

  1. 创建一个对 MATLAB 搜索路径可见的新工作文件夹。此示例使用 C:\Work 作为新工作文件夹。

  2. 在 Windows 和您计划运行 .NET 应用程序的其他平台上安装 MATLAB Runtime。有关详细信息,请参阅下载并安装 MATLAB Runtime

  3. 对于 Linux 和 macOS 平台,安装 MATLAB Runtime 后,您需要分别设置 LD_LIBRARY_PATHDYLD_LIBRARY_PATH 环境变量。有关详细信息,请参阅针对部署设置 MATLAB Runtime 路径

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

创建 MATLAB 函数

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

function result = ProcessMWObjectArray(obj)
    % Display the class type of the input
    disp(['Input is of type: ', class(obj)]);

    % Convert MWObjectArray to a MATLAB cell array
    matlabArray = cell(obj);

    % Display the contents and class type of each element in the array
    disp('Contents of the MWObjectArray:');
    for element = matlabArray
        disp(['Element: ', class(element{1})]);
        disp(element{1});
    end

    % Return the processed MATLAB array as the result
    result = matlabArray;
end

使用 MATLAB 外部语言接口 API 中的 NET.createArray 函数在 MATLAB 中创建 .NET 对象并测试该函数。

% Create a .NET object array with different types
netArray = NET.createArray('System.Object', 4);
netArray(1) = int32(42);               % Integer
netArray(2) = 3.14;                    % Double
netArray(3) = 'Hello, MATLAB!';        % String
netArray(4) = NET.createArray('System.Int32', [1, 2, 3]);  % .NET array

% Convert the .NET object array to a MATLAB cell array for convenience
matlabArray = cell(netArray);

% Call the MATLAB function with the MATLAB array
result = ProcessMWObjectArray(matlabArray);

% Display the result
disp('Processed MATLAB array:');
disp(result);
Input is of type: cell
Contents of the MWObjectArray:
Element: int32
   42
Element: double
    3.1400
Element: System.String
Hello, MATLAB!

Element: System.Int32[,,]
  Int32[,,] with properties:

            Length: 6
        LongLength: 6
              Rank: 3
          SyncRoot: [1×1 System.Int32[,,]]
        IsReadOnly: 0
       IsFixedSize: 1
    IsSynchronized: 0
Processed MATLAB array:
    {[42]}    {[3.1400]}    {1×1 System.String}    {1×1 System.Int32[,,]}

在 MATLAB 内部测试 ProcessMWObjectArray 函数时,不能将 .NET 对象直接转换为 MWObjectArray。因此,使用 MATLAB 元胞数组来模拟 MWObjectArray 行为。使用 MATLAB 元胞数组允许我们直接在 MATLAB 中测试函数,因为元胞数组可以保存不同类型的数据,类似于 MWObjectArray。这使得它们成为测试函数如何处理各种元素的良好替代品。从 C# 应用程序测试时,您可以创建一个 .NET 数组并将其转换为 MWObjectArray 以传递给 MATLAB 函数。

创建 .NET 程序集

使用 compiler.build.dotNETAssembly 函数创建一个 .NET 程序集。

buildResults = compiler.build.dotNETAssembly("ProcessMWObjectArray.m", ...
    Interface="mwarray",...
    Verbose="on", ...
    OutputDir=".\output", ...
    AssemblyName="MATLABExample", ClassName="MyMATLABFunctions")

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

该函数生成一套文件(如下所列),并将它们放在指定的输出目录中。

P:\MATLAB\WORK\OUTPUT
    GettingStarted.html
    includedSupportPackages.txt
    MATLABExample.dll
    MATLABExample.xml
    MATLABExampleNative.dll
    MATLABExampleNative.xml
    MATLABExampleVersion.cs
    MATLABExample_overview.html
    mccExcludedFiles.log
    MyMATLABFunctions.cs
    MyMATLABFunctionsNative.cs
    readme.txt
    requiredMCRProducts.txt
    unresolvedSymbols.txt

No subfolders exist

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

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

  2. 在命令行中,键入:

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

    这会创建一个名为 DotNetObjConsoleApp 的文件夹,其中包含以下内容:

    • obj 文件夹

    • DotNetObjConsoleApp.csproj 工程文件

    • Program.cs C# 源文件

  3. 在文本编辑器中打开工程文件。

    <Project Sdk="Microsoft.NET.Sdk">
    
      <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net6.0</TargetFramework>
      </PropertyGroup>
    
    </Project>

    使用 <ItemGroup> 标记将以下引用添加到工程中:

    • compiler.build.dotNETAssembly 函数创建的 MATLABExample.dll .NET 程序集文件。

    • MWArray.dll .NET 程序集文件依赖关系。

      如果您的系统上安装了 MATLAB

      • matlabroot\toolbox\dotnetbuilder\bin\win64\netstandard2.0\MWArray.dll

      如果您的系统上安装了 MATLAB

      • <MATLAB_RUNTIME_INSTALL_DIR>\toolbox\dotnetbuilder\bin\win64\netstandard2.0\MWArray.dll

    添加引用后,您的工程文件应类似于以下内容:

    <Project Sdk="Microsoft.NET.Sdk">
    
      <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net6.0</TargetFramework>
      </PropertyGroup>
    
        <ItemGroup>
        <Reference Include="MATLABExample">
          <HintPath>P:\MATLAB\work\output\MATLABExample.dll</HintPath>
    	  <!--Path to .NET Assembly created by compiler.build.dotNETAssembly function-->
        </Reference>
        <Reference Include="MWArray">
          <HintPath>C:\Program Files\MATLAB\R2025a\toolbox\dotnetbuilder\bin\win64\netstandard2.0\MWArray.dll</HintPath>
    	  <!--Path to MWArray.dll in the MATLAB-->
        </Reference>
      </ItemGroup>
    </Project>
  4. Program.cs C# 文件中的代码替换为以下代码:

     Program.cs

     Program.cs (macOS)

    常规 C# 应用程序代码和 macOS 版本之间的区别在于,Main 方法的原始内容现在位于 macOS 版本中名为 MyMainFunc 新创建的函数中。原始的 Main 方法现在只是使用 MWMCR.setupMacRunLoopAndRun 和命令行参量作为参数调用 MyMainFunc 方法。

    MWMCR.setupMacRunLoopAndRun 对于 macOS 环境来说是不可或缺的,因为它允许 MATLAB 与核心基础运行循环 (CFRunLoop) 交互,这是一种用于处理用户输入或计时器事件等事件的 macOS 特定机制。由于 macOS 上的 .NET 6.0 或 .NET Core 应用程序默认不会在主线程上设置 CFRunLoop(MATLAB 依赖它进行事件管理),因此 MWMCR.setupMacRunLoopAndRun 介入建立 CFRunLoop。这可确保 MATLAB 函数与在 macOS 上运行的 .NET 6.0 或 .NET Core 应用程序无缝集成,从而防止潜在的事件处理问题。

    注意

    仅当您在 macOS 上开发或运行 C# 应用程序时才需要使用 MWMCR.setupMacRunLoopAndRun

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

    dotnet build DotNetObjConsoleApp.csproj

运行 .NET 应用程序

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

!DotNetObjConsoleApp.exe
Input is of type: System.Object[]

Contents of the MWObjectArray:

Element: int32

   42

Element: double

    3.1400

Element: System.String

Hello, MATLAB!

Element: System.Int32[]

  Int32[] with properties:

            Length: 3
        LongLength: 3
              Rank: 1
          SyncRoot: [1x1 System.Int32[]]
        IsReadOnly: 0
       IsFixedSize: 1
    IsSynchronized: 0

[42]    [3.1400]    [1x1 opaque]    [1x1 opaque]

另请参阅

|