Implement Type-Safe Interface and Integrate into .NET Application
This example shows how to implement a type-safe interface and integrate it into a .NET application.
Type-safe interfaces allow you to work directly with familiar native data types instead
of using the MWArray API. Adding a type-safe interface to a .NET assembly
creates an additional set of methods that accept and return native .NET types.
Write and Test Your MATLAB Code
Create your MATLAB® program and then test the code before implementing a type-safe interface. The functions in your MATLAB program must match the declarations in your native .NET interface.
For this example, save the following code as multiply.m. The
function returns the multiplication of the inputs x and
y.
function z = multiply(x,y)
z = x * y;Test the function at the MATLAB command prompt.
multiply([1 4 7; 2 5 8; 3 6 9],[1 4 7; 2 5 8; 3 6 9])
ans =
30 66 102
36 81 126
42 96 150Implement Type-Safe Interface
After you write and test your MATLAB code, develop a .NET type-safe interface in either C# or Visual Basic®. This example uses provided C# source code for the interface.
Open Microsoft® Visual Studio® and create a new Class Library (.NET Framework) project named
IMultiply.In the Solution Explorer window, rename the
Class1.csfile toIMultiply.cs. In this file, you write source code for the type-safe interface that accesses the component.In this example, the
IMultiplyinterface is written in C# and specifies three overloads ofmultiply:using System; public interface IMultiply { // Scalar multiplication System.Double multiply(System.Double x, System.Double y); // Multiply vector by a scalar, return a vector System.Double[] multiply(System.Double[] x, System.Double y); // Matrix multiplication System.Double[,] multiply(System.Double[,] x, System.Double[,] y); }Each method in the interface must exactly match a deployed MATLAB function.
All methods have two inputs and one output (to match the MATLAB
multiplyfunction), though the parameter data type varies.Go to Build and then Configuration Manager, and change the platform from Any CPU to x64.
Build the project with Microsoft Visual Studio.
The file
IMultiply.dllis generated in the build folder.
This example assumes your assembly contains only IMultiply.
Realistically, it is more likely that the type-safe interface will already be part of a
compiled assembly. The assembly can be compiled even before the MATLAB function is written.
Create .NET Assembly Using .NET Assembly Compiler App
Generate the type-safe interface with the .NET assembly using the .NET Assembly Compiler app. Alternatively, if you want to create a .NET assembly from the MATLAB command window using a programmatic approach, see Create .NET Assembly Using compiler.build.dotNETAssembly.
Create a .NET Assembly Compiler project and select .NET Assembly from the Type list.
Specify the following values:
Field Value Library Name MultiplyClass Name ArithmeticFile to Compile multiply.mExpand the Additional Runtime Settings section.
In the Type-Safe API section, do the following:
Select Enable Type-Safe API.
In the Interface assembly field, specify the location of the type-safe interface assembly
IMultiply.dllthat you built.Select the
IMultiplyinterface from the .NET interface drop-down box.Leave the Namespace field blank.
Specify the
Arithmeticclass in the Wrapped Class field.
Click the Package button to build the project.
Create .NET Assembly Using compiler.build.dotNETAssembly
As an alternative to the .NET Assembly Compiler app, you can generate the type-safe interface using a programmatic approach using the following steps. If you have already created an assembly using the .NET Assembly Compiler, see Integrate .NET Assembly into .NET Application.
Build the .NET assembly using the
compiler.build.dotNETAssemblyfunction. Use name-value arguments to specify the assembly name and class name.compiler.build.dotNETAssembly('multiply.m', ... 'AssemblyName','Multiply', ... 'ClassName','Arithmetic');
Navigate to the generated
MultiplydotNETAssemblyfolder.Generate the type-safe interface by using the
ntswrapcommand from MATLAB:ntswrap('-c','Multiply.Arithmetic', ... '-a','IMultiply.dll', ... '-i','IMultiply');
Not all arguments are compatible with each other. See
ntswrapfor details on all command options.Tip
If the
IMultiply.dllassembly is not in the current folder, specify the full path.This command generates the assembly
ArithmeticIMultiply.dllthat contains a type-safe API for the MATLAB Compiler SDK™ classArithmeticin the namespaceMultiplyNative.
Integrate .NET Assembly into .NET Application
After creating your .NET assembly, you can integrate it into any .NET application. You can use this example .NET application code as a guide to write your own .NET application.
Compile the .NET program using Microsoft Visual Studio by doing the following steps:
Open Microsoft Visual Studio and create a C# Console App (.NET Framework) called
MultiplyApp.Copy the following source code into the generated
Program.csin your project:using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace MultiplyApp { class Program { delegate String VectorToString<T>(IEnumerable<T> v); delegate IEnumerable<String> MatrixToString<T>(T[,] m); static void Main(string[] args) { Console.WriteLine("\nStarting application...\n"); //Create an instance of the Type-safe API IMultiply m = new ArithmeticIMultiply(); // Scalar multiplication double x = 17, y = 3.14159; double z = m.multiply(x, y); System.Console.WriteLine("{0} * {1} = {2}\n", x, y, z); // Vector times scalar double[] v = new double[] { 2.5, 81, 64 }; double s = 11; double[] d = m.multiply(v, s); VectorToString<double> vec2str = (vec => vec.Select(n => n.ToString()).Aggregate((str, next) => str + " " + next)); System.Console.WriteLine("[ {0} ] * {1} = [ {2} ]\n", vec2str(v), s, vec2str(d)); // Matrix multiplication double[,] magic = new double[,]{ // 3x3 magic square { 8, 1, 6 }, { 3, 5, 7 }, { 4, 9, 2 } }; double[,] squareSquared = m.multiply(magic, magic); MatrixToString<double> mat2str = mat => mat.EnumerateRows<double>().Select(r => vec2str(r)); PrintParallel(mat2str(magic), " * ".Select(c => c.ToString()), mat2str(magic), " = ".Select(c => c.ToString()), mat2str(squareSquared)); Console.WriteLine("\nClosing application..."); } public static void PrintParallel<T>(params IEnumerable<T>[] sources) { int max = sources.Select(s => s.Count()).Max(); for (int i = 0; i < max; i++) { foreach (var src in sources) System.Console.Write("{0} ", src.ElementAt(i)); System.Console.WriteLine(); } } } public static class ArrayExtensions { public static IEnumerable<IEnumerable<T>> EnumerateRows<T>(this Array a) { return Enumerable.Range(0, a.GetLength(1)).Select(row => a.ToIEnumerable<T>().Skip(row * a.GetLength(0)).Take(a.GetLength(0))); } public static IEnumerable<T> ToIEnumerable<T>(this Array a) { foreach (var item in a) yield return (T)item; } } }Add references in the project to the following files.
This reference: Defines: IMultiply.dllThe .NET native type interface assembly IMultiplyArithmeticIMultiply.dllThe generated type-safe API MultiplyNative.dllThe generated .NET assembly Note
Unlike other .NET deployment scenarios, you do not need to reference
MWArray.dllin the server program source code. TheMWArraydata types are hidden behind the type-safe API inArithmeticIMultiply.Go to Build and then Configuration Manager, and change the platform from Any CPU to x64.
Compile and run the program with Microsoft Visual Studio.
The program displays the following output:
Starting application... 17 * 3.14159 = 53.40703 [ 2.5 81 64 ] * 11 = [ 27.5 891 704 ] 8 1 6 8 1 6 91 67 67 3 5 7 * 3 5 7 = 67 91 67 4 9 2 4 9 2 67 67 91 Closing application...
Tips
In a MATLAB function, declaration outputs appear before inputs. For example, in the
multiplyfunction, the outputzappears before the inputsxandy. This ordering is not required for .NET interface functions. Inputs may appear before or after outputs, or the two may be mixed together.MATLAB Compiler SDK matches .NET interface functions to public MATLAB functions by function name and argument count. In the
multiplyexample, both the .NET interface function and the MATLAB function must be namedmultiply, and both functions must have an equal number of arguments defined.The number and relative order of input and output arguments is critical.
In evaluating parameter order, only the order of like parameters (inputs or outputs) is considered, regardless of where they appear in the parameter list.
A function in the interface may have fewer inputs than its corresponding MATLAB function, but not more.
Argument mapping occurs according to argument order rather than argument name.
The function return value, if specified, counts as the first output.
You must use
outparameters for multiple outputs.Alternately, the
refparameter can be used forout, asrefandoutare synonymous.
MATLAB does not support overloading of functions. Thus, all user-supplied overloads of a function with a given name will map to a function generated by MATLAB Compiler SDK.
See .NET Types to MATLAB Types for complete guidelines in managing data conversion with type-safe interfaces.
See Also
compiler.build.dotNETAssembly | ntswrap