C#中常用的基本类型有int、double、string、bool、Byte等,matlab中的基本类型有double、single、int32、char、struct等等。
C#里面的数据类型就算是和matlab里面的名字相同也是无法直接使用的。因为在Matlab中基本上都是以矩阵的形式来组织数据,和C#中对于数据的处理方式完全不同。两者的互通必须通过MWArray这个类,在上一篇《MATLAB.NET混合编程之二》中就提到过这个类。matlab编译出给C#调用的dll(COM组件除外),基本上输入和输出都需要用到它。
根据资料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]代表列数,高维数组可以参考这种方法继续获取其他维度的长度。
使用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
Matlab中没有字符串的概念,它能够处理的是单个的字符,所以C#中的字符串传递给Matlab是使用字符串数组MWCharArray来完成。
和数字类型的转换方式类似,在C#中可以直接给MWCharArray变量赋值,也可以通过构造函数构造MWCharArray对象:
MWCharArray arr="this is an example";
MWCharArray arr=new MWCharArray("this is an example");
上面两者的效果是一样的。最终arr
内都是行矩阵,即行数为1,列数与字符串中字符数量相同的矩阵。
如果是使用C#数组给MWCharArray赋值,那么结果就是个行数与数组长度相同,列数与最大行字符数相同的矩阵,例如
MWCharArray arr=new MWCharArray(new string[]{"a","b","cd"});
上例中arr
最终就是个三行两列的字符矩阵。
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类型内部也是不关心数据类型的,也就是说可以存放任意的数据类型,可以是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的朋友应该是可以很容易看懂的。
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)中都可以直接识别,易用性较好。