Main Content

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 ...)
while .NET indexes as follows:
(... 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 ith 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.

 GetPrimes Using MWArray Query

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:

  1. 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

  2. Create a .NET object to pass to the MATLAB function.

         Dictionary char2Ascii= new Dictionary();
         char2Ascii.Add("A", 65);
         char2Ascii.Add("B", 66);
    
  3. Create an instance of MWObjectArray to wrap the .NET object.

    MWObjectArray MWchar2Ascii= 
               new MWObjectArray(char2Ascii);
    
  4. 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:

  1. 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
    
  2. Create the object.

    MyDouble myDouble= new MyDouble(75);
    
  3. Create an instance of MWObjectArray to wrap the .NET object.

    MWObjectArray MWdouble= new MWObjectArray(myDouble);
                origRef = new MWObjectArray(hash);

  4. Pass the wrapped object to the MATLAB function and retrieve the returned cloned object.

    MWObjectArray result= 
                (MWObjectArray)myComp.add(MWdouble, 25);
  5. 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 implements ICloneable, the Clone 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];
It is also possible to extract only the real or imaginary component of a complex matrix by calling the appropriate component indexing method.

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.

MWNumericArrays 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); 

Related Topics