MATLAB.NET混合编程之三~~从C#向Matlab的数据类型转化

C#中常用的基本类型有int、double、string、bool、Byte等,matlab中的基本类型有double、single、int32、char、struct等等。

C#里面的数据类型就算是和matlab里面的名字相同也是无法直接使用的。因为在Matlab中基本上都是以矩阵的形式来组织数据,和C#中对于数据的处理方式完全不同。两者的互通必须通过MWArray这个类,在上一篇《MATLAB.NET混合编程之二》中就提到过这个类。matlab编译出给C#调用的dll(COM组件除外),基本上输入和输出都需要用到它。

MWArray是什么?

根据资料1的解释,MWArray是MathWorks公司是为其他语言调用matlab编译的dll设计出的一种数据类型。它本身是抽象类,并且它是 MWNumericArray、MWLogicalArray、MWCharArray、MWStructArray和MWCellArray的基类(除了MWIndexArray,MWIndexArray本身也是抽象类)。这些子类都有诸如维度的属性,比如维度数,维度尺寸,元素长度,字段名等等。

数据类型的映射规则

下面这个表也是来源于资料一:

.NET Type MWArray Type MATLAB Type
System.Double MWNumericArray double
System.Number MWNumericArray double
System.Float MWNumericArray single
System.Byte MWNumericArray int8
System.Short MWNumericArray nt16
System.Int32 MWNumericArray int32
System.Int64 MWNumericArray int64
System.Char MWCharArray char
System.String MWCharArray char
System.Boolean MWLogicalArray logical
N/A MWStructArray structure
N/A MWCellArray cell

注意:遵循.NET CLS规范的语言不支持无符号的uint16、uint32和uint64,但这三个在Matlab中是支持的。所以给.net开发组件时,这三种类型的变量就不能被用于M函数中。最后的structure和cell这两种数据类型在.net中完全无法找到合适的对应类型,用N/A来表示。

如何传递数据

举个例子,某个Matlab提供的函数为MWArray demoFunction1(MWArray arr);如何使用呢?(因为所有的Matlab函数的参数都是MWArray,所以具体该怎么组织数据提供给Matlab的函数需要获取该函数的帮助文档或者直接去问函数的编写者。)

  • 假设需要输入的是单个数字

比如需要输入的是double、int等,如何传递参数?首先根据映射表,C#里面的数据类型都是对应于MWNumericArray,所以应该查找MWNumericArray的构造函数,如何以数据类型为参数构造一个新的MWNumericArray对象。

根据MWNumericArray构造函数参考手册,里面列举了约58种构造函数。比如double类型的就可以使用MWNumericArray(Double)这个构造函数构造对象。MWNumericArray num=new MWNumericArray(3.1415926)

除此之外,.net的数值类型也可以直接隐式转换为MWNumericArray。MWNumericArray num=3.1415926;

构造出MWNumericArray对象之后就可以直接给Matlab的函数赋值了,因为MWNumericArray可以隐式转化为MWArray。

  • 假设需要输入的是数字数组

根据手册的构造函数,可以将数组先赋值给MWNumericArray或者使用MWNumericArray(Int32[])构造函数构造MWNumericArray对象再给该对象赋值,最后将结果赋值给MWArray。

例如:

    MWNumericArray arr=new int[]{1,2,3,4};
    MWArray factor=arr;
    Console.WriteLine(arr.ToString());

输出结果是:1 2 3 4

注意,如果使用MWNumericArray arr=new MWNumericArray(new int[]{3,2});建立的MWNumericArray对象是一个三行两列的空矩阵,而不是个一行两列的矩阵。
它的结果是:

0   0
0   0
0   0
  • 假设是多维数字数组

多维数组怎么赋值?比如new int[,]{{1,2},{3,4}}。多维数组和一维数组是一样的,在Matlab看来并没有什么差别,只不过是维度不同的的矩阵而已,一维数组是1*n的矩阵,二维数组是m*n等等诸如此类。所以在用法上也没有什么差别,可以直接参考一维数组的用法。

查看数组各个维度的长度可以使用MWArray的Dimensions属性。这是个数组,Dimensions[0]代表行数,Dimensions[1]代表列数,高维数组可以参考这种方法继续获取其他维度的长度。

  • C#一维数组转换为Matlab二维矩阵

使用MWNumericArray(Int32, Int32,Double[])可以让C#的一维数组变为Matlab的二维数组:

    MWNumericArray arr = new MWNumericArray(2,2, new int[] { 1, 2, 3, 4 });
    Console.WriteLine(arr.ToString());

结果是:

1   2
3   4
  • C#字符串转化为Matlab矩阵

Matlab中没有字符串的概念,它能够处理的是单个的字符,所以C#中的字符串传递给Matlab是使用字符串数组MWCharArray来完成。

和数字类型的转换方式类似,在C#中可以直接给MWCharArray变量赋值,也可以通过构造函数构造MWCharArray对象:

MWCharArray arr="this is an example";
MWCharArray arr=new MWCharArray("this is an example");

上面两者的效果是一样的。最终arr内都是行矩阵,即行数为1,列数与字符串中字符数量相同的矩阵。

  • C#字符串数组转化为Matlab矩阵

如果是使用C#数组给MWCharArray赋值,那么结果就是个行数与数组长度相同,列数与最大行字符数相同的矩阵,例如

MWCharArray arr=new MWCharArray(new string[]{"a","b","cd"});

上例中arr最终就是个三行两列的字符矩阵。

  • MWStructArray

MWStructArray不关注具体的数据类型,使用的也不太多,一般情况下都可以使用其他类型的对象完成相关功能。使用方法:

MWStructArray arr = new MWStructArray(new int[] { 3, 3 }, new string[] { "a", "b", "c" });
arr["a", 1, 1] = "array";
arr["b", 1, 1] = 0;
arr["c", 1, 1] = 98989;
  • MWCellArray

MWCellArray类型是所有类型中功能最强大,使用也最复杂的类型。MWCellArray类型内部也是不关心数据类型的,也就是说可以存放任意的数据类型,可以是MWNumericArray,也可以是MWCharArray,因此表达方式非常灵活,适合用于各种场景。使用方法:

MWCellArray cel = new MWCellArray(3, 4);
cel[1, 1] = (MWNumericArray)new int[] { 1, 2, 3 };
cel[1, 2] = 1;
cel[1, 3] = "matlab";

限于篇幅,不可能将所有的数据转化方法都在此文中一一列出,如果文中的内容不能答疑解惑,最好的办法就是去查阅相关的API文档,那里的资料是最全面的,经常查看MSDN的朋友应该是可以很容易看懂的。

注意事项

  • 个人在测试中发现,如果项目的.net版本是4.5.2,那么在使用 MWNumericArray arr=new int[]{1,2,3,4};或其他方法给MWNumericArray对象初始化是会报错:“MathWorks.MATLAB.NET.Arrays.MWNumericArray”的类型初始值设定项引发异常。

解决办法:将.net版本切换成4.0(client profile也可以)

  • 在多维数组的使用过程中经常会发现有的数据不需要填充或者数据有错误怎么办?

解决办法:最好是在matlab函数开发过程中就约定好这类的数据使用什么来替代。假设接收的参数是不限制数据类型的,比如MWCellArray,那么可以使用null或者NAN等常见的符号来表示;假设matlab函数要求传入的是纯数字类型,比如MWNumericArray,可以使用“负无穷大”来表示,matlab和c#(double.NegativeInfinity)中都可以直接识别,易用性较好。

参考资料

  1. MWArrayAPI HELP
  2. Matlab中文论坛

你可能感兴趣的:(matlab,C#,net)