Main Content

Convert Data Between Java and MATLAB

When you invoke a MATLAB® method from a generated class in your Java® application, the input arguments received by the method must be in the MATLAB internal array format. You can either use manual conversion within the calling program by using instances of the MWArray classes, or rely on automatic conversion by storing your data using Java classes and data types, which are then automatically converted by the calling mechanism. Most likely, you will use a combination of manual and automatic conversion.

For example, consider the following Java statement:

result = theFourier.plotfft(3, data, Double.valueOf(interval));

The third argument is of type java.lang.Double, which is converted to a MATLAB 1-by-1 double array.

Automatic Conversion to MATLAB Types

The call signature for a method that encapsulates a MATLAB function uses one of the MATLAB data conversion classes to pass input and output arguments. When you call any such method, all input arguments not derived from one of the MWArray classes are automatically converted by the compiler to the correct MWArray type before being passed to the MATLAB method.

For tables showing each Java type along with its converted MATLAB type, and each MATLAB type with its converted Java type, see Rules for Data Conversion Between Java and MATLAB.

Use MWNumericArray

The getmagic program (Integrate Simple MATLAB Function into Java Application) converts a java.lang.Double argument to an MWNumericArray type that can be used by the MATLAB function without further conversion:

n = new MWNumericArray(Double.valueOf(args[0]), MWClassID.DOUBLE);
theMagic = new Class1();
result = theMagic.makesqr(1, n);

Pass Java Double Object

This example calls the myprimes method with two arguments. The first specifies the number of arguments to return. The second is an object of class java.lang.Double that passes the single data input to myprimes.

cls = new myclass();
y = cls.myprimes(1, Double.valueOf((double)n));

The compiler converts the java.lang.Double argument to a MATLAB 1-by-1 double array.

Pass MWArray

This example constructs an MWNumericArray of type MWClassID.DOUBLE. The call to myprimes passes the number of outputs, 1, and the MWNumericArray, x.

x = new MWNumericArray(n, MWClassID.DOUBLE);
cls = new myclass();
y = cls.myprimes(1, x);

The compiler converts the MWNumericArray object x to a MATLAB scalar double and passes it to the MATLAB function.

Call MWArray Methods

The conversion rules apply not only when calling your own methods, but also when calling constructors and factory methods belonging to the MWArray classes.

For example, the following code fragment calls the constructor for the MWNumericArray class with a Java double as the input argument:

double Adata = 24;
MWNumericArray A = new MWnumericArray(Adata);
System.out.println("Array A is of type " + A.classID());
Array A is of type double

The compiler converts the input argument to an instance of MWNumericArray with a ClassID property of MWClassID.DOUBLE. This MWNumericArray object is the equivalent of a MATLAB 1-by-1 double array.

Return Data from MATLAB to Java

All data returned from a method coded in MATLAB is passed as an instance of the appropriate MWArray subclass. For example, a MATLAB cell array is returned to the Java application as an MWCellArray object.

Return data is not converted to a Java type. If you choose to use a Java type, you must convert to that type using the toArray method of the MWArray subclass to which the return data belongs. For more details, see Use toTypeArray Methods to Specify Type and Dimensionality.

Note

For information on how to work directly with cell arrays and data structures in native Java, see Represent Native Java Cell and Struct Arrays.

Manual Conversion of Data Types

To manually convert to one of the standard MATLAB data types, use the MWArray data conversion classes provided by MATLAB Compiler SDK™. For class reference and usage information, see the com.mathworks.toolbox.javabuilder package.

Change Default by Specifying Type

When calling an MWArray class method constructor, supplying a specific data type causes MATLAB Compiler SDK to convert to that type instead of the default.

For example, in the following code fragment, the code specifies that A should be constructed as a MATLAB 1-by-1 16-bit integer array:

double Adata = 24;
MWNumericArray A = new MWnumericArray(Adata, MWClassID.INT16);
System.out.println("Array A is of type " + A.classID());
Array A is of type int16

Pass Variable Numbers of Inputs

Consider the following MATLAB function that returns the sum of the inputs:

function y = mysum(varargin)
y = sum([varargin{:}]);

The inputs are provided as a varargin argument, which means that the caller can specify any number of inputs to the function. The result is returned as a scalar double.

MATLAB Compiler SDK generates the following Java interface to this function:

/* mlx interface - List version*/
public void mysum(List lhs, List rhs)
                          throws MWException
{
   (implementation omitted)
}
/* mlx interface - Array version*/
public void mysum(Object[] lhs, Object[] rhs)
                          throws MWException
{
   (implementation omitted)
}

/* standard interface - no inputs */
public Object[] mysum(int nargout) throws MWException
{
   (implementation omitted)
}

/* standard interface - variable inputs */
public Object[] mysum(int nargout, Object varargin)
                          throws MWException
{
   (implementation omitted)
}

In all cases, the varargin argument is passed as type Object, which lets you provide any number of inputs in the form of an array of Object (Object[]). The contents of this array are passed to the compiled MATLAB function in the order in which they appear in the array.

Here is an example of how you might use the mysum method in a Java program:

public double getsum(double[] vals) throws MWException
{
   myclass cls = null;
   Object[] x = {vals};
   Object[] y = null;

   try
   {
      cls = new myclass();
      y = cls.mysum(1, x);
      return ((MWNumericArray)y[0]).getDouble(1);
   }

   finally
   {
      MWArray.disposeArray(y);
      if (cls != null)
	      cls.dispose();
   }
}

In this example, you create an Object array of length 1 and initialize it with a reference to the supplied double array. This argument is passed to the mysum method. The result is known to be a scalar double, so the code returns this double value with the statement:

return ((MWNumericArray)y[0]).getDouble(1);

Cast the return value to MWNumericArray and invoke the getDouble(int) method to return the first element in the array as a primitive double value.

Pass Array Inputs

This more general version of getsum takes an array of Object as input and converts each value to a double array. The list of double arrays is then passed to the mysum function, where it calculates the total sum of each input array.

public double getsum(Object[] vals) throws MWException
{
   myclass cls = null;
   Object[] x = null;
   Object[] y = null;

   try
   {
      x = new Object[vals.length];
      for (int i = 0; i < vals.length; i++)
         x[i] = new MWNumericArray(vals[i], MWClassID.DOUBLE);

      cls = new myclass();
      y = cls.mysum(1, x);
      return ((MWNumericArray)y[0]).getDouble(1);
   }
   finally
   {
      MWArray.disposeArray(x);
      MWArray.disposeArray(y);
      if (cls != null)
         cls.dispose();
   }
}

Pass Variable Number of Outputs

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. MATLAB Compiler SDK generates the following Java interface to this function:

/* mlx interface - List version */
 public void randvectors(List lhs, List rhs) throws MWException
{
   (implementation omitted)
}
/* mlx interface - Array version */
public void randvectors(Object[] lhs, 
           Object[] rhs) throws MWException
{
   (implementation omitted)
}
/* Standard interface - no inputs*/
public Object[] randvectors(int nargout) throws MWException
{
   (implementation omitted)
}

Pass Optional Arguments with Standard Interface

Here is one way to use the randvectors method in a Java program:

 getrandvectors.java

The getrandvectors method returns a two-dimensional double array with a triangular structure. The length of the ith row equals i. Such arrays are commonly referred to as jagged arrays. Jagged arrays are easily supported in Java because a Java matrix is just an array of arrays.

Handle Return Values of Unknown Type

The previous examples used the fact that you knew 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 several ways to do this:

  • Use reflection support in the Java language to query any object for its type.

  • Use several methods provided by the MWArray class to query information about the underlying MATLAB array.

  • Specify type using the toTypeArray methods.

Use Java Reflection to Determine Type and Dimensionality

This example uses the toArray method to return a Java primitive array representing the underlying MATLAB array. The toArray method works just like getData in the previous examples, except that the returned array has the same dimensionality as the underlying MATLAB array.

The code calls the myprimes method and determines the type using reflection. The example assumes that the output is returned as a numeric matrix, but the exact numeric type is unknown.

 getprimes.java Using Reflection

Use MWArray Query to Determine Type and Dimensionality

The next example uses the MWArray classID method to determine the type of the underlying MATLAB array. It also checks the dimensionality by calling numberOfDimensions. If any unexpected information is returned, an exception is thrown. It then checks the MWClassID and processes the array accordingly.

 getprimes.java Using classID

Use toTypeArray Methods to Specify Type and Dimensionality

The next example demonstrates how you can coerce or force data to a specified numeric type by invoking any of the toTypeArray methods. These methods return an array of Java elements of the type specified in the name of the called method. The data is coerced or forced to the primitive type specified in the method name. Note that when using these methods, data will be truncated when needed to allow conformance to the specified data type.

 Specify Type Using toTypeArray Method

Pass Java Objects by Reference

You can create a MATLAB code wrapper around Java objects using MWJavaObjectRef, a special subclass of MWArray. Using this technique, you can pass objects by reference to MATLAB functions, clone a Java object inside a generated package, as well as perform other object marshaling specific to MATLAB Compiler SDK. The examples in this section present some common use cases.

Pass Java Object into MATLAB Compiler SDK Java Method

To pass an object into a MATLAB Compiler SDK Java method:

  1. Use MWJavaObjectRef to wrap your object.

  2. Pass your object to a MATLAB function.

For example:

/* Create an object */
java.util.Hashtable<String,Integer> hash = 
                  new java.util.Hashtable<String,Integer>();
hash.put("One", 1);
hash.put("Two", 2);
System.out.println("hash: ");
System.out.println(hash.toString());
            
/* Create a MWJavaObjectRef to wrap this object */
origRef = new MWJavaObjectRef(hash);
            
/* Pass it to a MATLAB function that lists its methods, etc */
result = theComponent.displayObj(1, origRef);            
MWArray.disposeArray(origRef);

Clone an Object

You can also use MWJavaObjectRef to clone an object by doing the following:

  1. Add to the original hash.

  2. Clone the object.

  3. (Optional) Continue to add items to each copy.

For example:

origRef = new MWJavaObjectRef(hash);            
System.out.println("hash:");
System.out.println(hash.toString());
result = theComponent.addToHash(1, origRef);
            
outputRef = (MWJavaObjectRef)result[0];
            
/* We can typecheck that the reference contains a      */
/*        Hashtable but not <String,Integer>;          */
/* this can cause issues if we get a Hashtable<wrong,wrong>. */
java.util.Hashtable<String, Integer> outHash = 
          (java.util.Hashtable<String,Integer>)(outputRef.get());
            
/* We've added items to the original hash, cloned it, */
/* then added items to each copy */
System.out.println("hash:");
System.out.println(hash.toString());
System.out.println("outHash:");
System.out.println(outHash.toString());

 addToHash.m

Pass Date into Method and Get Date from Method

In addition to passing in created objects, you can also use MWJavaObjectRef to pass utility objects such as java.util.date.

  1. Get the current date and time using the Java object java.util.date.

  2. Create an instance of MWJavaObjectRef in which to wrap the Java object.

  3. Pass it to a MATLAB function that performs further processing, such as nextWeek.m.

For example:

/* Get the current date and time */
java.util.Date nowDate = new java.util.Date();
System.out.println("nowDate:");
System.out.println(nowDate.toString());
            
/* Create a MWJavaObjectRef to wrap this object */
origRef = new MWJavaObjectRef(nowDate);
            
/* Pass it to a MATLAB function that calculates one week */
/* in the future */
result = theComponent.nextWeek(1, origRef);
            
outputRef = (MWJavaObjectRef)result[0];
java.util.Date nextWeekDate = 
      (java.util.Date)outputRef.get();
System.out.println("nextWeekDate:");
System.out.println(nextWeekDate.toString());

 nextWeek.m

Return Java Objects Using unwrapJavaObjectRefs

If you want actual Java objects returned from a method, use unwrapJavaObjectRefs. This method recursively connects a single MWJavaObjectRef or a multidimensional array of MWJavaObjectRef objects to a reference or array of references.

The following code fragments show two examples of calling unwrapJavaObjectRefs:

 Return Single Reference or Reference to Array of Objects Using unwrapJavaObjectRefs

 Return Array of References Using unwrapJavaObjectRefs

Optimization Example Using MWJavaObjectRef

For a full example of how to use MWJavaObjectRef to create a reference to a Java object and pass it to a method, see Pass Java Objects to MATLAB.

See Also

|

Related Topics