Deploy MATLAB Function to .NET Application Using MATLAB Data API for .NET
Supported .NET Version: .NET 6.0 or higher
This example shows how to package a MATLAB® function and deploy it with a .NET application written in C#. The workflow is supported on Windows®, Linux®, and macOS systems. This example uses a workflow based on Windows.
Since R2023a, .NET applications with packaged MATLAB code can be developed and published across Windows, Linux, and macOS platforms. This means it's possible to develop on any one of these platforms and publish to any of the other two. Prior to that release, .NET applications could only be published from Windows to Linux and macOS.
Note that while development and publishing can happen on any platform, there may still be platform-specific nuances and issues. Some libraries or functionalities might behave differently on different platforms, and developers should test their applications thoroughly on the target platform to ensure expected behavior.
Prerequisites
Create a new work folder that is visible to the MATLAB search path. This example uses a folder named
work
.Verify that you have set up a .NET development environment. For details, see Set Up .NET Development Environment.
Verify that you have met all of the MATLAB .NET target requirements. For details, see MATLAB Compiler SDK .NET Target Requirements.
End users must have an installation of MATLAB Runtime to run the application. For details, see Download and Install MATLAB Runtime.
For testing purposes, you can use an installation of MATLAB instead of MATLAB Runtime.
Verify that you have .NET 6.0 SDK or higher or Microsoft® Visual Studio® 2022 (v17.0 or higher) installed. You can verify whether .NET 6.0 is installed by entering
dotnet --info
at a system command prompt. You can download a .NET SDK version specific to your operating system from https://dotnet.microsoft.com/download.
Data Management
To exchange data between the deployed MATLAB code and the .NET application, use the MATLAB Data API for .NET. This API is also used by MATLAB Engine. For an overview, see Call MATLAB from .NET. For details, see:
Create MATLAB Function
Create a MATLAB file named calculateDistance.m
with the following
code:
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
Established MATLAB users may find the presence of an arguments
block unconventional. The arguments
block lets you represent C# data
types with an equivalent MATLAB type. For instance, if your C# application employs an
Int64
data type representing a value, you can now represent that in
MATLAB as an int64
. This option is useful in situations where a
C# application has strict type requirements. For details, see Data Type Mappings Between .NET and Strongly Typed MATLAB Code.
In this example, an arguments
block with specified type
information is used to illuminate subtle nuances. However, remember that incorporating an
arguments
block is entirely optional. The deployment process
remains unchanged even without it. Various parts of this example underscore the areas
where this difference manifests. So, if data types aren't crucial, the specification of
type information using an arguments
block is not necessary.
Test the MATLAB function at the command prompt.
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
Create .NET Assembly Using compiler.build.dotNETAssembly
Create a code archive (.ctf
file), from the MATLAB function using the compiler.build.dotNETAssembly
function.
buildResults = compiler.build.dotNETAssembly("calculateDistance.m", Interface="matlab-data",... Verbose="on", OutputDir=".\output", AssemblyName="CalculateDistance")
Although supplying an assembly name via the AssemblyName
property
isn't mandatory, it's highly recommended. Doing so results in a cleaner namespace for the
generated .NET assembly and C# file. In its absence, a root namespace named
example
is automatically appended to the sub-namespace, leading to a
cluttered and potentially confusing namespace structure.
The function produces a suite of files, as enumerated below, and places them in the
specified output
directory. Among these, the key files utilized during
the integration process are the code archive (.ctf
file) containing the
MATLAB code, a C# (.cs
) code file, and a .NET assembly
(.dll
file). For information on the other files, see Files Generated After Packaging MATLAB Functions.
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
To finalize integration, you can choose one of two options:
Use the
CalculateDistance.ctf
code archive file in conjunction with thecalculateDistance.cs
C# code file.Use the
CalculateDistance.ctf
code archive file in conjunction with theCalculateDistance.dll
.NET assembly file.
Upon inspection, you notice that the function also generates a
CalculateDistance.csproj
project file. This file is generated
specifically to create the corresponding CalculateDistance.dll
.NET
assembly file. However, it should not be mistaken as a template for your .NET project and
must not be used in that context.
This example employs the first integration option to illustrate type mapping mechanics. Relevant guidance for using the second option is interjected at pertinent stages of the workflow.
You can inspect the content of the C# code file below:
In the calculateDistance.cs
C# code file, the MATLAB function's int64
argument specification mirrors its C#
equivalent, 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); } |
When an arguments
block detailing type information is not
included in your MATLAB function, it results in the production of the following C# code file:
calculateDistance.cs
(Type Agnostic)
The primary difference between the C# code files rests in the type specification for
input and output variables. When an arguments
block is used with type
information specified, the inputs and outputs are categorized as Int64
.
Conversely, when an arguments
block with type information is absent:
The inputs to the C# method must be of a type that the MATLAB function can handle. They are represented as having
dynamic
type in the C# code file. For mapping details, see Pass .NET Data Types to MATLAB Functions.In the C# code file, outputs from the MATLAB function are cast to types such as
MATLABArray
,MATLABObject
, orMATLABStruct
, depending on the function's return value. These must then be assigned to a corresponding C# type. If you use an incorrect type, aSystem.InvalidCastException
is thrown. For mapping details, see Handle MATLAB Data in .NET Applications.
The process of specifying input and output types often involves a considerable amount of referencing and educated guessing. Consequently, employing an arguments block containing type information can eliminate this ambiguity, thereby streamlining the development of C# applications that incorporate packaged MATLAB functions.
Note
The generated component does not include MATLAB Runtime or an installer. To create an installer using the
buildResults
object, see compiler.package.installer
.
Integrate MATLAB Code into .NET Application
You can finalize the integration process in your preferred C# development environment, including a text editor along with the .NET SDK Command Line API, or alternatives such as Microsoft Visual Studio on Windows and macOS. This example shows you how to complete the integration using both options. For details, see Set Up .NET Development Environment.
Use .NET SDK Command Line API to Build Application
If you are using Microsoft Visual Studio, see Use Microsoft Visual Studio to Build Application (Windows).
Open the command prompt in Windows and navigate to the
work
folder being used in this example.At the command line, enter:
dotnet new console --framework net6.0 --name DistanceConsoleApp
This command creates a folder named
DistanceConsoleApp
that contains the following:obj
folderDistanceConsoleApp.csproj
project fileProgram.cs
C# source file
Copy the following files produced by the
compiler.build.dotNETAssembly
function to the project folder created bydotnet new
, alongside theProgram.cs
C# application code file:.cs
C# wrapper files from the...\work\output\strongly_typed_interface\
directory.CalculateDistance.ctf
code archive from the...\work\output
directory.
Edit the project to add assembly dependencies and the
CalculateDistance.ctf
code archive file generated by thecompiler.build.dotNETAssembly
function.Open the project file in a text editor and include the following assemblies using a
<Reference>
tag within the<ItemGroup>
tag of the project:MathWorks.MATLAB.Runtime.dll
MathWorks.MATLAB.Types.dll
Note
If you use the
CalculateDistance.dll
.NET assembly generated by thecompiler.build.dotNETAssembly
function instead of the C# code file, include that as a reference within the same<ItemGroup>
tag.Include the
CalculateDistance.ctf
code archive file as a content file to the project.Add the
CalculateDistance.ctf
code archive file as a content file within the<ItemGroup>
tag.Add the tag
CopyToOutputDirectory
and set it toAlways
. This step ensures that theCalculateDistance.ctf
file is copied to the output folder during the build process. This means that when you build your project, this file is in the same directory as your built.exe
file.Add the tag
CopyToPublishDirectory
and set it toAlways
. This step ensures that theCalculateDistance.ctf
file is copied to the cross-platform folder to which this project is published.
Once you add the assembly dependencies and include
CalculateDistance.ctf
as a content file, your project file looks like the following:DistanceConsoleApp.csproj
(Windows)DistanceConsoleApp.csproj
(Linux)DistanceConsoleApp.csproj
(macOS)Note
If you choose to use the
CalculateDistance.dll
.NET assembly—generated bycompiler.build.dotNETAssembly
—over the C# code file, remember to uncomment the reference tags to theCalculateDistance.dll
in the project file. This change ensures your project correctly uses the.dll
file.Replace the code in the
Program.cs
C# file with the following code:Note
While developing and operating on macOS systems, transition the code from the
Main
method into a new function namedMainFunc
. Subsequently, invokeMATLABRuntime.SetupMacRunLoopAndRun
from within theMain
method and passMainFunc
along with the command-line arguments as parameters.MATLABRuntime.SetupMacRunLoopAndRun
is integral for macOS environments because it lets MATLAB interact with the Core Foundation Run Loop (CFRunLoop), a macOS-specific mechanism for handling events such as user inputs or timer events. For details, seeMathWorks.MATLAB.Runtime.MATLABRuntime
.When an
arguments
block detailing type information is not included in your MATLAB function, your C# application code must be written as follows:In the C# application code, when there isn't an
arguments
block detailing type information, you'll observe that the inputs are often specified asdouble
. While this is not a default setting, it's a practical choice since the default data type in MATLAB is adouble
. However, it's important to note that other types such asInt64
orInt32
could also be suitable depending on the specific requirements of your application, provided that the MATLAB function can handle these input types. The output variabledistance
is set to adynamic
type. This adaptable type is designed to inherit the type ofMATLABArray
as it is the return type of the MATLAB function. Following this assignment,distance
is cast as a C#double
for use within your program.Incorporating explicit type information within your MATLAB function using an
arguments
block can help eliminate assumptions about data types. This practice not only increases clarity but also enhances the robustness of your code by reducing potential type mismatch errors.At the command line, build your project by entering:
dotnet build DistanceConsoleApp.csproj
Run C# Application
For testing purposes, you can run the application from MATLAB command prompt. This does not require a MATLAB Runtime installation.
At the MATLAB command prompt, navigate to the directory containing the executable, and run your application by entering:
!dotnet run
The application displays the Euclidean distance between two points.
Euclidean distance between [0, 0] and [3, 4] is: 5
Note
When you're ready to deploy this application, ensure the target system has
MATLAB Runtime installed. For details, see Download and Install MATLAB Runtime. On Linux and macOS systems, you must set the LD_LIBRARY_PATH
and
DYLD_LIBRARY_PATH
runtime paths respectively, prior to running
your application. For details, see Set MATLAB Runtime Path for Deployment.
Use Microsoft Visual Studio to Build Application (Windows)
Open Microsoft Visual Studio and create a C# Console App named
DistanceConsoleApp
.Choose
.NET 6.0 (Long-term support)
as the framework.Swap out the default-generated source code in the
Program.cs
file with the specific source code provided in theProgram.cs
file found on this example page.Choose one of two options:
To incorporate the
calculateDistance.cs
C# code file generated by thecompiler.build.dotNETAssembly
function, navigate to Solution Explorer, right-click your project, and select Add > Existing Item. Use the dialog box to find and add thecalculateDistance.cs
C# code file.If you prefer to use the
CalculateDistance.dll
.NET assembly produced by thecompiler.build.dotNETAssembly
function, right-click your solution in Solution Explorer and choose Edit Project File. Here, you'll need to add a reference to theCalculateDistance.dll
file within the existing<ItemGroup>
tag.
View one of the above-listed project files as a reference.
Add the following assembly dependencies:
MathWorks.MATLAB.Runtime.dll
MathWorks.MATLAB.Types.dll
Add the
CalculateDistance.ctf
code archive file as a content file to the project. Right-click your project in Solution Explorer and select Add > Existing Item. In the dialog box, browse for the file and add the file.Right-click the
CalculateDistance.ctf
file in Solution Explorer and select Properties. In the Properties window, set Build Action to Content and Copy to Output Directory to Copy always.Right-click your project in Solution Explorer and select Edit Project File. The
DistanceConsoleApp.csproj
project file opens in the editor. Add the<CopyToPublishDirectory>
tag right below the<CopyToOutputDirectory>
tag and set it toAlways
. The edited portion of theDistanceConsoleApp.csproj
project file looks as follows:... <ItemGroup> <Content Include="CalculateDistance.ctf"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToPublishDirectory>Always</CopyToPublishDirectory> </Content> </ItemGroup> ...
On the menu bar, choose Build and choose Build Solution to build the application within Visual Studio.
The build process generates an executable named
DistanceConsoleApp.exe
.Run the application from Visual Studio by pressing Ctrl+F5. Alternatively, you can execute the generated executable from a system terminal:
> cd C:\work\DistanceConsoleApp\DistanceConsoleApp\bin\Debug\net6.0 > DistanceConsoleApp.exe
The application returns the same output as the sample MATLAB code.
Euclidean distance between [0, 0] and [3, 4] is: 5
Tip
If you are unable to run your application from Visual Studio, open the Developer Command Prompt for Visual Studio and start Visual Studio by entering
devenv /useenv
. Then, open your project and run your application.
Publish to Linux and macOS
Note
Before R2023a: Applications can only be published from Windows to Linux and macOS.
To publish the application to Linux, enter the following command on a single line at the system command prompt:
dotnet publish --configuration Release --framework net6.0 --runtime linux-x64 --self-contained true DistanceConsoleApp.csproj
To publish application to macOS, enter the following command on a single line:
dotnet publish --configuration Release --framework net6.0 --runtime osx.12-x64 --self-contained true DistanceConsoleApp.csproj
To publish to a specific platform, use the appropriate Runtime Identifier (RID). For details, see https://learn.microsoft.com/en-us/dotnet/core/rid-catalog.
Publish from Visual Studio
For details on how to set up publishing from Visual Studio, see the .NET documentation. Once setup is complete, edit your publish profile to contain the following settings:
Set Configuration to Release | Any CPU.
Set Target framework to net6.0.
Set Deployment mode to Self-contained.
Set Target runtime to linux-x64 or osx-x64.
Leave Target location unchanged or set it to a location of your choice.
Run Published Application on Linux
Copy the
Release
folder fromC:\work\DistanceConsoleApp\bin
on Windows to~/work
on a Linux machine. Create awork
folder on Linux if one does not already exist.On the Linux machine, verify that you have installed MATLAB Runtime and set up your
LD_LIBRARY_PATH
environment variable. For details, see Download and Install MATLAB Runtime and Set MATLAB Runtime Path for Deployment.Open a Linux console and navigate to:
~/work/Release/net6.0/linux-x64/publish
Add execute permissions to the Linux executable:
chmod +x DistanceConsoleApp
Run the application by entering:
./DistanceConsoleApp
Euclidean distance between [0, 0] and [3, 4] is: 5
Follow similar steps to run the application on macOS.
Note
You can use .NET Framework version 4.6.1
or higher to implement
this example. However, you cannot deploy the example across platforms. Also, .NET
Framework has no command-line interface.
See Also
compiler.build.dotNETAssembly
| compiler.build.DotNETAssemblyOptions
| MathWorks.MATLAB.Types.RunOptions
Related Topics
- Deploy MATLAB Classes to .NET Application Using MATLAB Data API for .NET
- MATLAB Compiler SDK .NET Target Requirements
- Download and Install MATLAB Runtime
- Pass .NET Data Types to MATLAB Functions
- Handle MATLAB Data in .NET Applications