Convert Data Between .NET and MATLAB
The MATLAB®
Compiler SDK™ product provides the MWArray
assembly to facilitate data
conversion between native data and compiled MATLAB functions. For information on the data conversion classes, see Data Marshaling with MWArray API.
Refer to the following examples for guidelines on how to marshal data between native .NET and MATLAB data types.
Note
Data objects that merely pass through either the target or MATLAB environments may not need to be marshaled, particularly if they do not cross a process boundary. Because marshaling is costly, only marshal on demand.
Manually Cast to MATLAB Types
Native Data Conversion
You can explicitly create a numeric constant using the constructor for the
MWNumericArray
class with a System.Int32
argument. You then pass this variable to one of the generated .NET methods.
int data = 24;
MWNumericArray array = new MWNumericArray(data);
Console.WriteLine("Array is of type " + array.NumericType);
When you run this example, the results are:
Array is of type double
The native integer (int data
) is converted to an
MWNumericArray
containing a 1-by-1 MATLAB double array, which is the default MATLAB type.
To preserve the integer type, use the MWNumericArray
constructor
that provides the ability to control the automatic conversion.
MWNumericArray array = new MWNumericArray(data, false);
Multidimensional Array Processing
MATLAB and .NET implement different indexing strategies for multidimensional
arrays. When you create a variable of type MWNumericArray
,
MATLAB automatically creates an equivalent array, using its own internal
indexing. For example, MATLAB indexes using this
schema:
(row column page1 page2 ...)
(... page2 page1 row column)
Given the multidimensional MATLAB
myarr
:
>> myarr(:,:,1) = [1, 2, 3; 4, 5, 6]; >> myarr(:,:,2) = [7, 8, 9; 10, 11, 12]; >> myarr myarr(:,:,1) = 1 2 3 4 5 6 myarr(:,:,2) = 7 8 9 10 11 12
You would code this equivalent in .NET:
double[,,] myarr = {{{1.000000, 2.000000, 3.000000},
{4.000000, 5.000000, 6.000000}}, {{7.000000, 8.000000,
9.000000}, {10.000000, 11.000000, 12.000000}}};
MWNumericArray Example
Here is a code fragment that shows how to convert a double
value
(5.0
) to a MWNumericArray
type:
MWNumericArray arraySize = 5.0;
magicSquare = magic.MakeSqr(arraySize);
After converting and assigning the double
value to the variable
arraySize
, you can use the arraySize
argument
with the MATLAB based method without further conversion. In this example, the MATLAB based method is magic.MakeSqr(arraySize)
.
Specify Array Type
If you want to create a MATLAB numeric array of a specific type, set the optional
makeDouble
argument to False
. The native type
then determines the type of the MATLAB array that is created.
Here, the code specifies that the array should be constructed as a MATLAB 1-by-1 16-bit integer array:
short data = 24;
MWNumericArray array = new MWNumericArray(data, false);
Console.WriteLine("Array is of type " + array.NumericType);
Running this example produces the following results:
Array is of type int16
Specify Optional Arguments
In MATLAB, you can use varargin
and varargout
to specify arguments that are not required. Consider the following MATLAB function:
function y = mysum(varargin)
y = sum([varargin{:}]);
This function returns the sum of the inputs. The inputs are provided as a
varargin
, which means that the caller can specify any number of
inputs to the function. The result is returned as a scalar double
array.
For the mysum
function, the MATLAB
Compiler SDK product generates the following interfaces:
// Single output interfaces
public MWArray mysum()
public MWArray mysum(params MWArray[] varargin)
// Standard interface
public MWArray[] mysum(int numArgsOut)
public MWArray[] mysum(int numArgsOut,
params MWArray[] varargin)
// feval interface
public void mysum(int numArgsOut, ref MWArray ArgsOut,
params MWArray[] varargin)
You can pass the varargin
arguments as either an
MWArray[]
, or as a list of explicit input arguments. (In C#, the
params
modifier for a method argument specifies that a method
accepts any number of parameters of the specific type.) Using params
allows your code to add any number of optional inputs to the encapsulated MATLAB function.
Here is an example of how you might use the single output interface of the
mysum
method in a .NET application:
static void Main(string[] args])
{
MWArray sum= null;
MySumClass mySumClass = null;
try
{
mySumClass= new MySumClass();
sum= mySumClass.mysum((double)2, 4);
Console.WriteLine("Sum= {0}", sum);
sum= mySumClass.mysum((double)2, 4, 6, 8);
Console.WriteLine("Sum= {0}", sum);
}
}
The number of input arguments can vary.
Note
For this particular signature, you must explicitly cast the first argument to
MWArray
or a type other than integer. Doing this distinguishes
the signature from the method signature, which takes an integer as the first argument.
If the first argument is not explicitly cast to MWArray
or as a
type other than integer, the argument can be mistaken as representing the number of
output arguments.
Pass a Variable Number of Outputs
When present, varargout
arguments are handled in the same way
that varargin
arguments are handled. Consider the following
MATLAB function:
function varargout = randvectors() for i=1:nargout varargout{i} = rand(1, i); end
This function returns a list of random double
vectors such that
the length of the i
th vector is equal to i
. The
MATLAB
Compiler SDK product generates the following .NET interface to this function:
public void randvectors()
public MWArray[] randvectors(int numArgsOut)
public void randvectors(int numArgsOut, ref MWArray[] varargout)
In this example, you use the standard interface and request two output arguments.
MyVarargOutClass myClass = new MyVarargOutClass();
MWArray[] results = myClass.randvectors(2);
Console.WriteLine("First output= {0}", results[0]);
Console.WriteLine("Second output= {0}", results[1]);
Pass Input Arguments
The following examples show generated code for the myprimes
MATLAB function, which has the following definition:
function p = myprimes(n)
p = primes(n);
Construct a Single Input Argument
The following sample code constructs data
as a
MWNumericArray
to be passed as input argument:
MWNumericArray data = 5;
MyPrimesClass myClass = new MyPrimesClass();
MWArray primes = myClass.myprimes(data);
Pass a Native .NET Type
This example passes a native double type to the function.
MyPrimesClass myClass = new MyPrimesClass();
MWArray primes = myClass.myprimes((double)13);
The input argument is converted to a MATLAB 1-by-1 double array, as required by the MATLAB function. This is the default conversion rule for a native double type. For a discussion of the default data conversion for all supported .NET types, see Rules for Data Conversion Between .NET and MATLAB.
Use the feval Interface
The feval
interface passes both input and output arguments on the
right-hand side of the function call. The output argument primes
must
be preceded by a ref
attribute.
MyPrimesClassmyClass = new MyPrimesClass();
MWArray[] maxPrimes = new MWArray[1];
maxPrimes[0] = new MWNumericArray(13);
MWArray[] primes = new MWArray[1];
myClass.myprimes(1, ref primes, maxPrimes);
Query Type of Return Value
The previous examples show guidelines to use if you know the type and dimensionality of the output argument. Sometimes in MATLAB programming this information is unknown, or can vary. In this case, the code that calls the method might need to query the type and dimensionality of the output arguments.
There are two ways to make the query:
Use .NET reflection to query any object for its type.
Use any of several methods provided by the
MWArray
class to query information about the underlying MATLAB array.
.NET Reflection
You can use reflection to dynamically create an instance of a type, bind the type to an existing object, or get the type from an existing object. You can then invoke the type's methods or access its fields and properties. For more information on reflection, see the MSDN Library.
The following code sample calls the myprimes
method and then
determines the type using reflection. The example assumes that the output is returned as
a numeric vector array, but the exact numeric type is unknown.
GetPrimes Using .NET Reflection
The example uses the toVector
method to return a .NET primitive
array (primesArray
), which represents the underlying MATLAB array. See the following code fragment from the example:
primes= myPrimesClass.myprimes((double)n);
Array primesArray= ((MWNumericArray)primes).
ToVector(MWArrayComponent.Real);
The toVector
is a method of the MWNumericArray
class. It returns a copy of the array component in column major order. The type of the
array elements is determined by the data type of the numeric array.
MWArray Query
This example uses the MWNumericArray
NumericType
method, along with MWNumericType
enumeration to determine the type of the underlying MATLAB array. See the switch (numericType)
statement.
The code in the example also checks the dimensionality by calling
NumberOfDimensions
; see the following code fragment:
if ((!primes.IsNumericArray) || (2 !=
primes.NumberofDimensions))
{
throw new ApplicationException("Bad type returned
by mwprimes");
}
This call throws an exception if the array is not numeric and of the proper dimension.
Pass Objects by Reference
MWObjectArray
, a special subclass of MWArray
,
lets you create a MATLAB array that references .NET objects.
You can create a MATLAB code wrapper around .NET objects using MWObjectArray
. Use
this technique to pass objects by reference to MATLAB functions and return .NET objects. The examples in this section present some
common use cases.
Pass .NET Object into .NET Assembly
To pass an object into a MATLAB Compiler SDK assembly:
Write the MATLAB function that references a .NET type.
function addItem(hDictionary, key, value) if ~isa(hDictionary,'System.Collections.Generic.IDictionary') error('foo:IncorrectType', ... 'expecting a System.Collections.Generic.Dictionary'); end hDictionary.Add(key, value); end
Create a .NET object to pass to the MATLAB function.
Dictionary char2Ascii= new Dictionary(); char2Ascii.Add("A", 65); char2Ascii.Add("B", 66);
Create an instance of
MWObjectArray
to wrap the .NET object.MWObjectArray MWchar2Ascii= new MWObjectArray(char2Ascii);
Pass the wrapped object to the MATLAB function.
myComp.addItem(MWchar2Ascii,'C', 67);
Return Custom .NET Object in MATLAB Function Using Deployed .NET Assembly
You can use MWObjectArray
to clone an object inside a MATLAB
Compiler SDK .NET assembly. Continuing with the previous example, perform the following
steps:
Write the MATLAB function that references a .NET type.
function result= add(hMyDouble, value) if ~isa(hMyDouble,'MyDoubleComp.MyDouble') error('foo:IncorrectType', 'expecting a MyDoubleComp.MyDouble'); end hMyDoubleClone= hMyDouble.Clone(); result= hMyDoubleClone.Add(value); end
Create the object.
MyDouble myDouble= new MyDouble(75);
Create an instance of
MWObjectArray
to wrap the .NET object.MWObjectArray MWdouble= new MWObjectArray(myDouble); origRef = new MWObjectArray(hash);
Pass the wrapped object to the MATLAB function and retrieve the returned cloned object.
MWObjectArray result= (MWObjectArray)myComp.add(MWdouble, 25);
Unwrap the .NET object and print the result.
MyDouble doubleClone= (MyDouble)result.Object; Console.WriteLine(myDouble.ToDouble()); Console.WriteLine(doubleClone.ToDouble());
Clone MWObjectArray
When calling the Clone
method on
MWObjectArray
, the following rules apply for the wrapped
object:
If the wrapped object is a
ValueType
, it is deep-copied.If an object is not a
ValueType
and implementsICloneable
, theClone
method for the object is called.The
MemberwiseClone
method is called on the wrapped object.
MWObjectArray aDate = new MWObjectArray(new
DateTime(1, 1, 2010));
MWObjectArray clonedDate = aDate.Clone();
Optimization Using MWObjectArray
For a full example of how to use MWObjectArray
to create a
reference to a .NET object and pass it to a component, see Integrate MATLAB Optimization Routines with Objective Functions.
MWObjectArray and Application Domains
Every ASP .NET web application deployed to IIS is started in a separate
AppDomain
.
The MATLAB .NET interface must support the .NET type wrapped by
MWObjectArray
. If the MWObjectArray
is created
in the default AppDomain
, the wrapped type has no other
restrictions.
If the MWObjectArray
is not created in the default
AppDomain
, the wrapped .NET type must be serializable. This
limitation is imposed by the fact that the object needs to be marshaled from the
non-default AppDomain
to the default AppDomain
in
order for MATLAB to access it.
MWObjectArray Limitation
If you have any global objects in your C# code, then you will get a Windows® exception on exiting the application. To overcome this limitation, use one of these solutions:
Explicitly clear global objects before exiting the application.
globalObj.Destroy();
Call
TerminateApplicationEx
method before exiting the application.MWMCR.TerminateApplicationEx();
For more information on
TerminateApplicationEx
, see the MWArray Class Library Reference.
Access Real or Imaginary Components Within Complex Arrays
Component Extraction
When you access a complex array (an array made up of both real and imaginary data), you extract both real and imaginary parts (called components) by default. This method call extracts both real and imaginary components:
MWNumericArray complexResult= complexDouble[1, 2];
Component Indexing on Complex Numeric Arrays
To return the real or imaginary component from a full complex numeric array, call
the .real
or .imaginary
method on
MWArrayComponent
.
complexResult= complexDouble[MWArrayComponent.Real, 1, 2];
complexResult= complexDouble[MWArrayComponent.Imaginary, 1, 2];
To assign the real or imaginary component to a full complex numeric array, call the
.real
or .imaginary
method on
MWArrayComponent
.
matrix[MWArrayComponent.Real, 2, 2]= 5;
matrix[MWArrayComponent.Imaginary, 2, 2]= 7:
You can return the real or imaginary component from a sparse complex numeric array in Microsoft® Visual Studio® 8 and later.
complexResult= sparseComplexDouble[MWArrayComponent.Real, 4, 3];
complexResult = sparseComplexDouble[MWArrayComponent.Imaginary, 4, 3];
Convert MATLAB Arrays to .NET Arrays
To convert MATLAB arrays to .NET arrays call the toArray
method with
either the .real
or .imaginary
method on
MWArrayComponent
.
Array nativeArray_real= matrix.ToArray(MWArrayComponent.Real);
Array nativeArray_imag= matrix.ToArray(MWArrayComponent.Imaginary);
Convert MATLAB Arrays to .NET Vectors
To convert MATLAB vectors to .NET vectors (single dimension arrays) call the
.real
or .imaginary
method on
MWArrayComponent
.
Array nativeArray= sparseMatrix.ToVector(MWArrayComponent.Real);
Array nativeArray= sparseMatrix.ToVector(MWArrayComponent.Imaginary);
Jagged Array Processing
A jagged array is an array whose elements are arrays. The elements of a jagged array can be of different dimensions and sizes, as opposed to the elements of a non–jagged array whose elements are of the same dimensions and size.
Web services, in particular, process data almost exclusively in jagged arrays.
MWNumericArray
s can only process jagged arrays with a rectangular
shape.
In the following code snippet, a rectangular jagged array of type
int
is initialized and populated.
int[][] jagged = new int[5][];
for (int i = 0; i < 5; i++)
jagged[i] = new int[10];
MWNumericArray jaggedMWArray = new MWNumericArray(jagged);
Console.WriteLine(jaggedMWArray);