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 i
th 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:
The getrandvectors
method returns a two-dimensional
double
array with a triangular structure. The length of the
i
th 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
to
Type
Array
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.
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.
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 toType
Array 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.
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:
Use
MWJavaObjectRef
to wrap your object.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:
Add to the original hash.
Clone the object.
(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());
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
.
Get the current date and time using the Java object
java.util.date
.Create an instance of
MWJavaObjectRef
in which to wrap the Java object.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());
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
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.