在 .NET 和 MATLAB 之间转换数据
MATLAB® Compiler SDK™ 产品提供了 MWArray 程序集,以促进本机数据和编译的 MATLAB 函数之间的数据转换。有关数据转换类的信息,请参阅使用 MWArray API 进行数据编组。
有关如何在本机 .NET 和 MATLAB 数据类型之间编组数据的指南,请参阅以下示例。
注意
仅仅穿过目标或 MATLAB 环境的数据对象可能不需要被编组,特别是当它们不跨越进程边界时。由于编组成本高昂,因此仅按需编组。
手动转换为 MATLAB 类型
本机数据转换
您可以使用带有 MWNumericArray 参量的 System.Int32 类的构造函数明确创建一个数字常量。然后将此变量传递给生成的 .NET 方法之一。
int data = 24;
MWNumericArray array = new MWNumericArray(data);
Console.WriteLine("Array is of type " + array.NumericType);运行此示例时,结果如下:
Array is of type double
本机整数 (int data) 被转换为包含 1×1 MATLAB 双精度数组的 MWNumericArray,这是默认的 MATLAB 类型。
为了保留整数类型,请使用提供控制自动转换功能的 MWNumericArray 构造函数。
MWNumericArray array = new MWNumericArray(data, false);多维数组处理
MATLAB 和 .NET 对多维数组实现了不同的索引策略。当您创建 MWNumericArray 类型的变量时,MATLAB 会使用其自己的内部索引自动创建一个等效数组。例如,MATLAB 使用以下架构建立索引:
(row column page1 page2 ...)
(... page2 page1 row column)
给定多维 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
您可以在 .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 示例
以下代码片段显示了如何将 double 精度值 (5.0) 转换为 MWNumericArray 类型:
MWNumericArray arraySize = 5.0;
magicSquare = magic.MakeSqr(arraySize);将 double 值转换并赋值给变量 arraySize 后,您可以将 arraySize 参量与基于 MATLAB 方法一起使用,而无需进一步转换。在此示例中,基于 MATLAB 的方法是 magic.MakeSqr(arraySize)。
指定数组类型
如果要创建特定类型的 MATLAB 数字数组,请将可选 makeDouble 参量设置为 False。然后,本机类型决定了创建的 MATLAB 数组的类型。
这里,代码指定数组应构建为 MATLAB 1×1 16 位整数数组:
short data = 24;
MWNumericArray array = new MWNumericArray(data, false);
Console.WriteLine("Array is of type " + array.NumericType);
运行此示例将产生以下结果:
Array is of type int16
指定可选参量
在 MATLAB 中,您可以使用 varargin 和 varargout 来指定不需要的参量。考虑以下 MATLAB 函数:
function y = mysum(varargin)
y = sum([varargin{:}]);
此函数返回输入的总和。输入以 varargin 形式提供,这意味着调用者可以为该函数指定任意数量的输入。结果以标量 double 数组形式返回。
对于 mysum 函数,MATLAB Compiler SDK 产品生成以下接口:
// 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)您可以将 varargin 参量作为 MWArray[] 或显式输入参量列表传递。(在 C# 中,方法参量的 params 修饰符指定方法接受任意数量的特定类型的参数。)使用 params 允许您的代码向封装的 MATLAB 函数添加任意数量的可选输入。
下面是如何在 .NET 应用程序中使用 mysum 方法的单一输出接口的示例:
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);
}
}输入参量的数量可以有所不同。
注意
对于这个特定的签名,您必须明确将第一个参量转换为 MWArray 或整数以外的类型。这样做可以将签名与方法签名区分开来,方法签名以整数作为第一个参量。如果第一个参量没有明确转换为 MWArray 或整数以外的类型,则该参量可能会被误认为代表输出参量的数量。
传递可变数量的输出
当存在时,varargout 参量的处理方式与 varargin 参量的处理方式相同。考虑以下 MATLAB 函数:
function varargout = randvectors() for i=1:nargout varargout{i} = rand(1, i); end
此函数返回随机 double 向量列表,其中第 i 个向量的长度等于 i。MATLAB Compiler SDK 产品为该函数生成以下 .NET 接口:
public void randvectors()
public MWArray[] randvectors(int numArgsOut)
public void randvectors(int numArgsOut, ref MWArray[] varargout)在此示例中,您使用标准接口并请求两个输出参量。
MyVarargOutClass myClass = new MyVarargOutClass();
MWArray[] results = myClass.randvectors(2);
Console.WriteLine("First output= {0}", results[0]);
Console.WriteLine("Second output= {0}", results[1]);传递输入参量
以下示例显示了 myprimes MATLAB 函数的生成代码,其定义如下:
function p = myprimes(n)
p = primes(n);构造单个输入参量
以下示例代码将 data 构造为 MWNumericArray 以作为输入参量传递:
MWNumericArray data = 5;
MyPrimesClass myClass = new MyPrimesClass();
MWArray primes = myClass.myprimes(data);传递本机 .NET 类型
此示例将本机双精度类型传递给函数。
MyPrimesClass myClass = new MyPrimesClass();
MWArray primes = myClass.myprimes((double)13);根据 MATLAB 函数的要求,输入参量被转换为 MATLAB 1×1 双精度数组。这是本机双精度类型的默认转换规则。有关所有受支持的 .NET 类型的默认数据转换的讨论,请参阅.NET 与 MATLAB 之间的数据转换规则。
使用 feval 界面
feval 接口在函数调用的右侧传递输入和输出参量。输出参量 primes 前面必须有一个 ref 属性。
MyPrimesClassmyClass = new MyPrimesClass();
MWArray[] maxPrimes = new MWArray[1];
maxPrimes[0] = new MWNumericArray(13);
MWArray[] primes = new MWArray[1];
myClass.myprimes(1, ref primes, maxPrimes);
返回值的查询类型
如果您知道输出参量的类型和维数,前面的示例将显示可用的指导原则。有时在 MATLAB 编程中这些信息是未知的,或者可能会有所不同。在这种情况下,调用该方法的代码可能需要查询输出参量的类型和维数。
有两种方法可以进行查询:
使用 .NET 反射来查询任何对象的类型。
使用
MWArray类提供的几种方法中的任意一种来查询有关底层 MATLAB 数组的信息。
.NET 反射
您可以使用反射来动态创建类型的实例,将类型绑定到现有对象,或者从现有对象获取类型。然后您可以调用该类型的方法或访问其字段和属性。有关反射的详细信息,请参阅 MSDN 库。
以下代码示例调用 myprimes 方法,然后使用反射确定类型。该示例假定输出作为数字向量数组返回,但确切的数值类型未知。
该示例使用 toVector 方法返回 .NET 原始数组 (primesArray),该数组表示底层 MATLAB 数组。请参阅以下示例中的代码片段:
primes= myPrimesClass.myprimes((double)n);
Array primesArray= ((MWNumericArray)primes).
ToVector(MWArrayComponent.Real);toVector 是 MWNumericArray 类的方法。它按列主顺序返回数组组件的副本。数组元素的类型由数值数组的数据类型决定。
MWArray 查询
此示例使用 MWNumericArray NumericType 方法以及 MWNumericType 枚举来确定底层 MATLAB 数组的类型。请参阅 switch (numericType) 语句。
示例中的代码还通过调用 NumberOfDimensions 检查维数;请参阅以下代码片段:
if ((!primes.IsNumericArray) || (2 !=
primes.NumberofDimensions))
{
throw new ApplicationException("Bad type returned
by mwprimes");
}如果数组不是数字且维数不正确,则此调用会引发异常。
通过引用传递对象
MWObjectArray 是 MWArray 的一个特殊子类,它允许您创建引用 .NET 对象的 MATLAB 数组。
您可以使用 MWObjectArray 围绕 .NET 对象创建 MATLAB 代码包装器。使用此技术通过引用 MATLAB 函数传递对象并返回 .NET 对象。本节中的示例介绍了一些常见的用例。
将 .NET 对象传递到 .NET 程序集
要将对象传递到 MATLAB Compiler SDK 程序集:
编写引用 .NET 类型的 MATLAB 函数。
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
创建一个 .NET 对象传递给 MATLAB 函数。
Dictionary char2Ascii= new Dictionary(); char2Ascii.Add("A", 65); char2Ascii.Add("B", 66);创建一个
MWObjectArray实例来包装 .NET 对象。MWObjectArray MWchar2Ascii= new MWObjectArray(char2Ascii);将包装的对象传递给 MATLAB 函数。
myComp.addItem(MWchar2Ascii,'C', 67);
使用已部署的 .NET 程序集在 MATLAB 函数中返回自定义 .NET 对象
您可以使用 MWObjectArray 克隆 MATLAB Compiler SDK .NET 程序集内的对象。继续前面的示例,执行以下步骤:
编写引用 .NET 类型的 MATLAB 函数。
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
创建对象。
MyDouble myDouble= new MyDouble(75);创建一个
MWObjectArray实例来包装 .NET 对象。MWObjectArray MWdouble= new MWObjectArray(myDouble); origRef = new MWObjectArray(hash);将包装的对象传递给 MATLAB 函数并检索返回的克隆对象。
MWObjectArray result= (MWObjectArray)myComp.add(MWdouble, 25);解开 .NET 对象并打印结果。
MyDouble doubleClone= (MyDouble)result.Object; Console.WriteLine(myDouble.ToDouble()); Console.WriteLine(doubleClone.ToDouble());
克隆 MWObjectArray
在 Clone 上调用 MWObjectArray 方法时,包装对象适用以下规则:
如果包装的对象是
ValueType,则会进行深度复制。如果对象不是
ValueType并且实现了ICloneable,则调用该对象的Clone方法。在包装的对象上调用
MemberwiseClone方法。
MWObjectArray aDate = new MWObjectArray(new
DateTime(1, 1, 2010));
MWObjectArray clonedDate = aDate.Clone();使用 MWObjectArray 进行优化
有关如何使用 MWObjectArray 创建对 .NET 对象的引用并将其传递给组件的完整示例,请参阅将 MATLAB 优化程序与目标函数集成。
MWObjectArray 和应用领域
部署到 IIS 的每个 ASP .NET Web 应用程序都在单独的 AppDomain 中启动。
MATLAB .NET 接口必须支持 MWObjectArray 包装的 .NET 类型。如果在默认的 MWObjectArray 中创建 AppDomain,则包装类型没有其他限制。
如果未在默认的 MWObjectArray 中创建 AppDomain,则包装的 .NET 类型必须是可序列化的。此限制是由于以下事实造成的:为了让 MATLAB 访问对象,需要将其从非默认 AppDomain 编组到默认 AppDomain。
MWObjectArray 限制
如果您的 C# 代码中有任何全局对象,那么退出应用程序时将出现 Windows® 异常。要克服此限制,请使用以下解决方案之一:
在退出应用程序之前明确清除全局对象。
globalObj.Destroy();在退出应用程序之前调用
TerminateApplicationEx方法。MWMCR.TerminateApplicationEx();有关
TerminateApplicationEx的详细信息,请参阅 MWArray 类库参考。
访问复数数组中的实部或虚组件
组件提取
当您访问复数数组(由实部和虚部数据组成的数组)时,默认情况下会提取实部和虚部(称为组件)。此方法调用提取实部和虚组件:
MWNumericArray complexResult= complexDouble[1, 2];复杂数值数组上的组件索引
要从完整的复数数字数组返回实部或虚组件,请调用 .real 上的 .imaginary 或 MWArrayComponent 方法。
complexResult= complexDouble[MWArrayComponent.Real, 1, 2];
complexResult= complexDouble[MWArrayComponent.Imaginary, 1, 2];要将实部或虚组件配给完整复数数值数组,请调用 .real 上的 .imaginary 或 MWArrayComponent 方法。
matrix[MWArrayComponent.Real, 2, 2]= 5;
matrix[MWArrayComponent.Imaginary, 2, 2]= 7:您可以从 Microsoft® Visual Studio® 8 及更高版本中的稀疏复数数组中返回实部或虚组件。
complexResult= sparseComplexDouble[MWArrayComponent.Real, 4, 3];
complexResult = sparseComplexDouble[MWArrayComponent.Imaginary, 4, 3];
将 MATLAB 数组转换为 .NET 数组
要将 MATLAB 数组转换为 .NET 数组,请使用 toArray 上的 .real 或 .imaginary 方法调用 MWArrayComponent 方法。
Array nativeArray_real= matrix.ToArray(MWArrayComponent.Real);
Array nativeArray_imag= matrix.ToArray(MWArrayComponent.Imaginary);将 MATLAB 数组转换为 .NET 向量
要将 MATLAB 向量转换为 .NET 向量(单维数组),请调用 .real 上的 .imaginary 或 MWArrayComponent 方法。
Array nativeArray= sparseMatrix.ToVector(MWArrayComponent.Real);
Array nativeArray= sparseMatrix.ToVector(MWArrayComponent.Imaginary);
锯齿状数组处理
交错数组是一种元素为数组的数组。交错数组的元素可以具有不同的维度和大小,而非交错数组的元素则具有相同的维度和大小。
特别是 Web 服务,几乎完全以锯齿状数组的形式处理数据。
MWNumericArray 只能处理矩形形状的锯齿状数组。
在下面的代码片段中,初始化并填充了 int 类型的矩形锯齿数组。
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);
