主要内容

本页采用了机器翻译。点击此处可查看最新英文版本。

JavaMATLAB 之间转换数据

当您从 MATLAB® 应用程序中生成的类调用 Java® 方法时,该方法接收的输入参量必须采用 MATLAB 内部数组格式。您可以通过使用 MWArray 类的实例在调用程序中进行手动转换,也可以通过使用 Java 类和数据类型存储数据来依靠自动转换,然后由调用机制自动转换。最有可能的是,您将使用手动和自动转换的组合。

例如,考虑以下 Java 语句:

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

第三个参量是 java.lang.Double 类型,它被转换为 MATLAB 1×1double 数组。

自动转换为 MATLAB 类型

封装 MATLAB 函数的方法的调用签名使用 MATLAB 数据转换类之一来传递输入和输出参量。当您调用任何此类方法时,所有未从 MWArray 类派生的输入参量都会由编译器自动转换为正确的 MWArray 类型,然后再传递给 MATLAB 方法。

有关显示每种 Java 类型及其转换后的 MATLAB 类型以及每种 MATLAB 类型及其转换后的 Java 类型的表格,请参阅Java 与 MATLAB 之间的数据转换规则

使用 MWNumericArray

getmagic 程序(使用 Java 包编译器创建 Java 包) 将 java.lang.Double 参量转换为 MWNumericArray 类型,该类型可供 MATLAB 函数使用,无需进一步转换:

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

传递 Java 双精度对象

此示例使用两个参量调用 myprimes 方法。第一个指定要返回的参量的数量。第二个是 java.lang.Double 类的对象,它将单个数据输入传递给 myprimes

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

编译器将 java.lang.Double 参量转换为 MATLAB 1×1double 数组。

传递 MWArray

此示例构造了一个 MWNumericArray 类型的 MWClassID.DOUBLE。对 myprimes 调用传递了输出数量 1MWNumericArray x

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

编译器将 MWNumericArray 对象 x 转换为 MATLAB 标量 double 并将其传递给 MATLAB 函数。

调用 MWArray 方法

转换规则不仅适用于调用您自己的方法时,也适用于调用属于 MWArray 类的构造函数和工厂方法时。

例如,以下代码片段使用 Java MWNumericArray 作为输入参量调用 double 类的构造函数:

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

编译器将输入参量转换为 MWNumericArray 的实例,其 ClassID 属性为 MWClassID.DOUBLE。这个 MWNumericArray 对象等效于 MATLAB 的 1×1double 数组。

将数据从 MATLAB 返回到 Java

从 MATLAB 中编码的方法返回的所有数据都作为适当的 MWArray 子类的实例传递。例如,MATLAB 元胞数组作为 MWCellArray 对象返回给 Java 应用程序。

返回数据转换为 Java 类型。如果您选择使用 Java 类型,则必须使用返回数据所属的 toArray 子类的 MWArray 方法转换为该类型。有关详细信息,请参阅使用类型数组方法来指定类型和维数

注意

有关如何直接使用原生 Java 中的元胞数组和数据结构的信息,请参阅表示本机 Java 单元和结构体数组

手动转换数据类型

要手动转换为标准 MATLAB 数据类型之一,请使用 MATLAB Compiler SDK™ 提供的 MWArray 数据转换类。有关类参考和使用信息,请参阅 com.mathworks.toolbox.javabuilder 包。

通过指定类型更改默认值

调用 MWArray 类方法构造函数时,提供特定的数据类型会导致 MATLAB Compiler SDK 转换为该类型而不是默认类型。

例如,在下面的代码片段中,代码指定应将 A 构造为 MATLAB 1×1 16 位整数数组:

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

传递可变数量的输入

考虑以下返回输入总和的 MATLAB 函数:

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

输入以 varargin 参量提供,这意味着调用者可以为函数指定任意数量的输入。结果以 double 标量形式返回。

MATLAB Compiler SDK 为该函数生成以下 Java 接口:

/* 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)
}

在所有情况下,varargin 参量都以 Object 类型传递,这允许您以 Object 数组 (Object[]) 的形式提供任意数量的输入。该数组的内容按照它们在数组中出现的顺序传递给已编译的 MATLAB 函数。

下面是如何在 Java 程序中使用 mysum 方法的示例:

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();
   }
}

在此示例中,您创建一个长度为 1 的 Object 数组,并使用对所提供的 double 数组的引用对其进行初始化。该参量传递给 mysum 方法。已知结果是一个标量 double,因此代码使用以下语句返回这个 double 值:

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

将返回值转换为 MWNumericArray 并调用 getDouble(int) 方法以原始 double 值形式返回数组中的第一个元素。

传递数组输入

这个更通用的 getsum 版本以 Object 数组作为输入,并将每个值转换为 double 数组。然后将 double 数组列表传递给 mysum 函数,在该函数中计算每个输入数组的总和。

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();
   }
}

传递可变数量的输出

varargout 参量的处理方式与 varargin 参量的处理方式相同。考虑以下 MATLAB 函数:

function varargout = randvectors

for i=1:nargout
   varargout{i} = rand(1, i);
end

此函数返回随机 double 向量列表,其中第 i 个向量的长度等于 i。MATLAB MATLABCompiler SDK 为该函数生成以下 Java 接口:

/* 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)
}

使用标准接口传递可选参量

以下是在 Java 程序中使用 randvectors 方法的一种方法:

 getrandvectors.java

getrandvectors 方法返回具有三角结构的二维 double 精度数组。第 i 行的长度等于 i。此类数组通常称为锯齿状数组。Java 很容易支持交错数组,因为 Java 矩阵只是数组的数组。

处理未知类型的返回值

前面的示例使用了您知道输出参量的类型和维数的事实。有时,在 MATLAB 编程中,这些信息是未知的或可能会有所不同。在这种情况下,调用该方法的代码可能需要查询输出参量的类型和维数。

有几种方法可以做到这一点:

  • 使用 Java 语言中的反射支持来查询任何对象的类型。

  • 使用 MWArray 类提供的几种方法来查询有关底层 MATLAB 数组的信息。

  • 使用 toTypeArray 方法指定类型

使用 Java 反射确定类型和维度

此示例使用 toArray 方法返回表示底层 Java 数组的 MATLAB 原始数组。toArray 方法的工作方式与前面示例中的 getData 类似,只是返回的数组具有与底层 MATLAB 数组相同的维数。

代码调用 myprimes 方法并使用反射确定类型。该示例假设输出作为数字矩阵返回,但确切的数值类型未知。

 使用反射的 getprimes.java

使用 MWArray 查询确定类型和维数

下一个示例使用 MWArray classID 方法来确定底层 MATLAB 数组的类型。它还通过调用 numberOfDimensions 来检查维数。如果返回任何意外信息,则会引发异常。然后它检查 MWClassID 并相应地处理数组。

 getprimes.java 使用 classID

使用类型数组方法来指定类型和维数

下一个示例演示如何通过调用任何 Type 数组方法将数据强制转换为指定的数值类型。这些方法返回被调用方法的名称中指定类型的 Java 元素数组。数据被强制或强制为方法名称中指定的基本类型。请注意,使用这些方法时,数据将在需要时被截断以符合指定的数据类型。

 使用类型 Type 方法指定类型

通过引用传递 Java 对象

您可以使用 MWJavaObjectRef MWArray 的一个特殊子类) 在 MATLAB 对象周围创建 Java 代码包装器。使用此技术,您可以通过引用 MATLAB 函数传递对象,在生成的包内克隆 Java 对象,以及执行特定于 MATLAB Compiler SDK 的其他对象编组。本节中的示例介绍了一些常见的用例。

Java 对象传递到 MATLAB Compiler SDK Java 方法

要将对象传递到 MATLAB Compiler SDK Java 方法:

  1. 使用 MWJavaObjectRef 来包装您的对象。

  2. 将您的对象传递给 MATLAB 函数。

例如:

/* 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);

克隆对象

您还可以使用 MWJavaObjectRef 克隆对象,方法如下:

  1. 添加到原始哈希中。

  2. 克隆对象。

  3. (可选)继续向每个副本添加项。

例如:

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

将日期传递到方法并从方法中获取日期

除了传递创建的对象之外,您还可以使用 MWJavaObjectRef 传递实用工具对象,例如 java.util.date

  1. 使用 Java 对象 java.util.date 获取当前日期和时间。

  2. 创建一个 MWJavaObjectRef 实例来包装 Java 对象。

  3. 将其传递给执行进一步处理的 MATLAB 函数,例如 nextWeek.m

例如:

/* 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

使用 unwrapJavaObjectRefs 返回 Java 对象

如果您希望从方法返回实际的 Java 对象,请使用 unwrapJavaObjectRefs。此方法以递归方式将单个 MWJavaObjectRefMWJavaObjectRef 对象的多维数组连接到引用或引用数组。

以下代码片段展示了调用 unwrapJavaObjectRefs 的两个示例:

 使用 unwrapJavaObjectRefs 返回单个引用或对象数组的引用

 使用 unwrapJavaObjectRefs 返回引用数组

使用 MWJavaObjectRef 的优化示例

有关如何使用 MWJavaObjectRef 创建对 Java 对象的引用并将其传递给方法的完整示例,请参阅将 Java 对象传递给 MATLAB

另请参阅

|

主题