将接受结构体数组作为输入参量的 MATLAB 函数部署到 .NET 应用程序
支持的 .NET 版本:.NET 6.0 或更高版本
数据 API:MATLAB® Data Array for .NET
此示例说明如何打包接受结构体数组作为输入的 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 函数
使用以下代码创建一个名为 analyzeData.m 的 MATLAB 文件:
function outputStruct = analyzeData(inputStruct) % This function takes a MATLAB struct 'inputStruct' as input, performs % statistical analysis on each numeric field, and returns a struct % 'outputStruct' containing the results of these analyses. Non-numeric % fields in the input struct are ignored. % % Inputs: % inputStruct - Struct with fields containing numeric data. % % Outputs: % outputStruct - Struct with the same fields as 'inputStruct'. Each % field is a struct with 'mean', 'std', and 'max' % of the corresponding field in 'inputStruct'. % % Use arguments block to map a MATLAB type to a C# type % Struct arrays in MATLAB map to a MATLAB Data Array % MATLABStruct type in C# arguments (Input) inputStruct (1,1) struct end arguments (Output) outputStruct (1,1) struct end % Initialize outputStruct outputStruct = struct(); % Get field names from the input struct fields = fieldnames(inputStruct); % Loop over each field and perform analysis for i = 1:length(fields) fieldName = fields{i}; % Ensure the field contains numeric data if isnumeric(inputStruct.(fieldName)) % Calculate mean outputStruct.(fieldName).mean = mean(inputStruct.(fieldName)); % Calculate standard deviation outputStruct.(fieldName).std = std(inputStruct.(fieldName)); % Calculate max value outputStruct.(fieldName).max = max(inputStruct.(fieldName)); else warning('Field %s is not numeric and was skipped.', fieldName); end end end
资深 MATLAB 用户可能会发现 arguments 模块的存在不太寻常。arguments 模块允许您用等效的 MATLAB 类型表示 C# 数据类型。
在命令提示符下测试 MATLAB 函数。
data = struct(); data.temperatures = [72, 75, 69, 68, 70]; data.pressures = [30, 29.5, 30.2, 29.9, 30.1]; output = analyzeData(data) output.temperatures(:) output.pressures(:)
output =
struct with fields:
temperatures: [1×1 struct]
pressures: [1×1 struct]
ans =
struct with fields:
mean: 70.8000
std: 2.7749
max: 75
ans =
struct with fields:
mean: 29.9400使用 compiler.build.dotNETAssembly 创建 .NET 程序集
使用 compiler.build.dotNETAssembly 函数从 MATLAB 函数创建代码存档(.ctf 文件)。
buildResults = compiler.build.dotNETAssembly("analyzeData.m", Interface="matlab-data",... Verbose="on", OutputDir=".\output", AssemblyName="AnalyzeData")
尽管通过 AssemblyName 属性提供程序集名称不是强制性的,但强烈建议这样做。这样做会为生成的 .NET 程序集和 C# 文件提供更清晰的命名空间。如果没有它,名为 example 的根命名空间会自动追加到子命名空间,从而导致命名空间结构混乱且可能令人困惑。
该函数生成一套文件(如下所列),并将它们放在指定的 output 目录中。其中,集成过程中使用的关键文件是包含 MATLAB 代码的代码存档(.ctf 文件)、C# (.cs) 代码文件和 .NET 程序集(.dll 文件)。有关其他文件的信息,请参阅打包 MATLAB 函数后生成的文件。
P:\MATLAB\WORK\OUTPUT
│ AnalyzeData.csproj
│ AnalyzeData.ctf
│ AnalyzeData.deps.json
│ AnalyzeData.dll
│ GettingStarted.html
│ includedSupportPackages.txt
│ mccExcludedFiles.log
│ readme.txt
│ requiredMCRProducts.txt
│ unresolvedSymbols.txt
│
└───strongly_typed_interface
analyzeData.cs要完成集成,您可以选择以下两个选项之一:
将
AnalyzeData.ctf代码存档文件与analyzeData.csC# 代码文件结合使用。将
AnalyzeData.ctf代码存档文件与AnalyzeData.dll.NET 程序集文件结合使用。
经检查,您会注意到该函数还生成一个 AnalyzeData.csproj 工程文件。该文件是专门为创建相应的 AnalyzeData.dll .NET 程序集文件而生成的。但是,它不应被误认为是 .NET 工程的模板,并且不得在该环境中使用。
此示例采用第一个集成选项来说明类型映射机制。在工作流的相关阶段插入了使用第二种选项的相关指导。
您可以检查以下 C# 代码文件的内容:
在 analyzeData.cs C# 代码文件中,MATLAB 函数的 struct 参量规范映射到基于 MATLAB 数据数组的 C# 等效项 MATLABStruct。
arguments (Input) inputStruct (1,1) struct end | MATLABStruct inputStruct |
arguments (Output) outputStruct (1,1) struct end | public static void analyzeData(MATLABProvider _matlab,
MATLABStruct inputStruct, out MATLABStruct outputStruct){
dynamic _dynMatlab = _matlab;
outputStruct =
(MATLABStruct)_dynMatlab.analyzeData(new RunOptions(nargout:1),inputStruct);
} |
将 MATLAB 代码集成到 .NET 应用程序中
您可以在首选的 C# 开发环境中完成集成过程,包括文本编辑器以及 .NET SDK 命令行 API,或者 Windows 和 Microsoft macOS 上的 Visual Studio 等替代方案。此示例向您说明如何使用两个选项完成集成。有关详细信息,请参阅设置 .NET 开发环境。
使用 .NET SDK 命令行 API 构建应用程序
如果您使用的是 Microsoft Visual Studio,请参阅使用 Microsoft Visual Studio 构建应用程序 (Windows)。
在 Windows 中打开命令提示符并导航到本示例中使用的
work文件夹。在命令行中输入:
dotnet new console --framework net6.0 --name StructConsoleApp此命令创建一个名为
StructConsoleApp的文件夹,其中包含以下内容:obj文件夹StructConsoleApp.csproj工程文件Program.csC# 源文件
将由
compiler.build.dotNETAssembly函数生成的以下文件与dotnet newC# 应用程序代码文件一起复制到Program.cs创建的工程文件夹中:来自
.cs目录的...\work\output\strongly_typed_interface\C# 包装器文件。来自
...\work\output目录的代码存档AnalyzeData.ctf。
编辑工程以添加程序集依赖项和由
compiler.build.dotNETAssembly函数生成的AnalyzeData.ctf代码存档文件。在文本编辑器中打开工程文件,并使用以下程序集包含
<Reference>标记内的<ItemGroup>工程标记:MathWorks.MATLAB.Runtime.dllMathWorks.MATLAB.Types.dll
注意
如果您使用由
compiler.build.dotNETAssembly函数生成的AnalyzeData.dll.NET 程序集而不是 C# 代码文件,请将其作为引用包含在同一个<ItemGroup>标记。将
AnalyzeData.ctf代码存档文件作为内容文件包含到工程中。将
AnalyzeData.ctf代码存档文件作为内容文件添加进<ItemGroup>标记。添加标记
CopyToOutputDirectory并将其设置为Always。此步骤确保在构建过程中将AnalyzeData.ctf文件复制到输出文件夹。这意味着当您构建工程时,该文件与您构建的.exe文件位于同一目录中。添加标记
CopyToPublishDirectory并将其设置为Always。此步骤确保将AnalyzeData.ctf文件复制到此工程发布到的跨平台文件夹中。
一旦添加了程序集依赖项并将
AnalyzeData.ctf作为内容文件包含进来,您的工程文件将如下所示:
StructConsoleApp.csproj(Windows)
StructConsoleApp.csproj(Linux)
StructConsoleApp.csproj(macOS)注意
如果您选择在 C# 代码文件上使用由
compiler.build.dotNETAssembly生成的AnalyzeData.dll.NET 程序集,请记住取消注释工程文件中对AnalyzeData.dll的引用标记。此更改可确保您的工程正确使用.dll文件。将
Program.csC# 文件中的代码替换为以下代码:注意
在 macOS 系统上开发和操作时,将代码从
Main方法转换到名为MainFunc的新函数。随后,从MATLABRuntime.SetupMacRunLoopAndRun方法中调用Main,并将MainFunc与命令行参量一起作为参数传递。MATLABRuntime.SetupMacRunLoopAndRun 对于 macOS 环境来说是不可或缺MATLABRuntime.SetupMacRunLoopAndRun,因为它允许 MATLAB 与 Core Foundation Run Loop (CFRunLoop) 交互,这是一种特定于 macOS 的机制,用于处理用户输入或计时器事件等事件。有关详细信息,请参阅MathWorks.MATLAB.Runtime.MATLABRuntime。在命令行中,输入以下命令来构建您的工程:
dotnet build StructConsoleApp.csproj
运行 C# 应用程序
为了测试目的,您可以从 MATLAB 命令提示符运行该应用程序。这不需要安装 MATLAB Runtime。
在 MATLAB 命令提示符下,导航到包含可执行文件的目录,然后输入以下内容运行您的应用程序:
!dotnet run应用程序显示平均值。
Field: temperatures mean: 70.8000 std: 2.7749 max: 75.0000 Field: pressures mean: 29.9400 std: 0.2702 max: 30.2000
注意
当您准备部署此应用程序时,请确保目标系统已安装 MATLAB Runtime。有关详细信息,请参阅下载并安装 MATLAB Runtime。在 Linux 和 macOS 系统上,必须在运行应用程序之前分别设置 LD_LIBRARY_PATH 和 DYLD_LIBRARY_PATH 运行时路径。有关详细信息,请参阅针对部署设置 MATLAB Runtime 路径。
使用 Microsoft Visual Studio 构建应用程序 (Windows)
打开 Microsoft Visual Studio 并创建一个名为
StructConsoleApp的 C# Console App。选择
.NET 6.0 (Long-term support)作为框架。将
Program.cs文件中默认生成的源代码替换为此示例页面中的Program.cs文件中提供的特定源代码。选择以下两个选项之一:
要合并由
compiler.build.dotNETAssembly函数生成的analyzeData.csC# 代码文件,请导航到 Solution Explorer,右键点击您的工程,然后选择 Add > Existing Item。使用对话框查找并添加analyzeData.csC# 代码文件。如果您更喜欢使用由
compiler.build.dotNETAssembly函数生成的AnalyzeData.dll.NET 程序集,请在 Solution Explorer 中右键点击您的解决方案,然后选择 Edit Project File。在这里,您需要在现有文件中添加对AnalyzeData.dll文件的引用<ItemGroup>标记。
查看上面列出的工程文件之一作为参考。
添加以下程序集依赖项:
MathWorks.MATLAB.Runtime.dllMathWorks.MATLAB.Types.dll
将
AnalyzeData.ctf代码存档文件作为内容文件添加到工程中。在 Solution Explorer 中右键点击您的工程,然后选择 Add > Existing Item。在对话框中,浏览文件并添加文件。在 Solution Explorer 中右键点击
AnalyzeData.ctf文件并选择 Properties。在 Properties 窗口中,将 Build Action 设置为 Content,并将 Copy to Output Directory 设置为 Copy always。在 Solution Explorer 中右键点击您的工程并选择 Edit Project File。
StructConsoleApp.csproj工程文件在编辑器中打开。添加<CopyToPublishDirectory>标记正下方<CopyToOutputDirectory>标记并将其设置为Always。StructConsoleApp.csproj工程文件的已编辑部分如下所示:... <ItemGroup> <Content Include="AnalyzeData.ctf"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToPublishDirectory>Always</CopyToPublishDirectory> </Content> </ItemGroup> ...在菜单栏上,选择 Build,然后选择 Build Solution 以在 Visual Studio 中构建应用程序。
编译过程会生成一个名为
StructConsoleApp.exe的可执行文件。按 Ctrl+F5 从 Visual Studio 运行应用程序。或者,您可以从系统终端执行生成的可执行文件:
> cd C:\work\StructConsoleApp\StructConsoleApp\bin\Debug\net6.0 > StructConsoleApp.exe
应用程序会返回与 MATLAB 示例代码相同的输出。
Field: temperatures mean: 70.8000 std: 2.7749 max: 75.0000 Field: pressures mean: 29.9400 std: 0.2702 max: 30.2000
提示
如果您无法构建应用程序,请将解决方案平台从
Any CPU更改为x64。如果您无法从 Visual Studio 运行应用程序,请打开 Developer Command Prompt for Visual Studio,然后输入
devenv /useenv启动 Visual Studio。然后,打开您的工程并运行您的应用程序。
另请参阅
compiler.build.dotNETAssembly | compiler.build.DotNETAssemblyOptions | MathWorks.MATLAB.Types.RunOptions
主题
- 使用 MATLAB Data API for .NET 将 MATLAB 函数部署到 .NET 应用程序
- 使用 MATLAB Data API for .NET 将 MATLAB 类部署到 .NET 应用程序
- 将接受元胞数组作为输入参量的 MATLAB 函数部署到 .NET 应用程序
- MATLAB Compiler SDK .NET 目标要求
- 下载并安装 MATLAB Runtime
- Pass .NET Data Types to MATLAB Functions
- Handle MATLAB Data in .NET Applications