关于matlab与c#混合编程的问题

更新时间:2024-01-28 12:11:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

关于matlab与c#混合编程的问题

2012-06-06 00:45shulai1008 | 浏览 1573 次

在c#中输入相应的函数,如何把这个函数传递给matlab中的m文件,并且是按照函数来识别的

分享到: 2012-06-06 11:08

再不玩“疯狂攀岩”你就OUT啦!

提问者采纳

你是指,参数传递吧,怎么会有函数传递呢

以下代码,供你参考,涉及到参数转换和传递,不懂的再补充吧 using System;

using System.Collections.Generic; using System.Linq; using System.Text;

using MathWorks.MATLAB.NET.Arrays;//在MWArray.dll,最常用的 using MathWorks.MATLAB.NET.Utility;// 在MWArray.dll,最常用的 using test_erfc;// 我在matlab中采样deploytool编译成test_erfc.dll namespace erfccc {

class Program {

static void Main(string[] args) {

test_erfc.test_erfcclass E = new test_erfcclass(); Console.WriteLine(\输入x的值:\

int x = Convert.ToInt32(Console.ReadLine());

MWArray[] result = E.erfc(1, (MWArray)x); //第一个参数取决于你的erfc有几个返回参数

MWNumericArray r1 = (MWNumericArray)result[0];

double[,] location1 = (double[,])r1.ToArray(MWArrayComponent.Real); Console.WriteLine(location1[0, 0].ToString()); Console.ReadLine(); } } } 追问:

我的意思是如何将如sin(x)/x这样的表达式传递给matlab,完成从c#中输入表达式和积分上下限求积分的功能

追答:

这个我就不懂了,我也不知道能不能实现,

如果是将表达式在matlab代码中固定,在C#中只传积分上下限的话可以实现

追问:

嗯,那也还是谢谢你了

追答:

如果你的函数有限,建议你还是写在matlab程序里,通过整型参数来识别用哪个函数

Matlab和C#混合编程

作者: gxyfish (站内联系TA) 发布: 2013-11-14

在实验室算法演示和工程应用中存在这样的困惑:

1. Matlab精通各种数值计算和算法,但是没有优美的界面,更不用说对数据库访问操作。 2.Visual studio(C#)拥有完美的界面编程,窗口或网络编程已经优越的数据库访问等优势。 -------------------------------------------------------------

3. 国外有一本书叫:MATLAB C# Book图书(已经放到压缩包中了),看过以后收获不少。 4. 结合各种材料,我使用visual studio 2012+ matlab 2013a实现了从 Winfrom调用Matlab命令行绘图

Winfrom调用 .m文件编译的dll并在webBrowser中显示结果

调用Matlab命令demo

调用Dll demo

解决方案结构

压缩包中包含MATLABCSharp.pdf

【原创】Matlab与.NET基于类型安全的接口混合编程入门

回到目录

1.前言

Matlab Builder NE 工具箱是与C#混编的工具箱,里面的帮助文档很详细,提供了4种情况下与.NET混合编程的案例。

1.是简单的组件集成,通过Matlab生成Dll程序集,在.NET环境中,通过MWArray组件来调用;

2.还有一个是在Web环境下使用Figure和混编的情况,与1比较类似;

3.另外一个就是我们今天要讲到的基于类型安全的接口编程,以及对WCF和MEF的支持; 4.最后一个是在.NET Remoting技术中的使用。

在初级入门教程中,以及我现在的混编开发中,都只是用到了第1个方法,和很简单,也很快,当然要你掌握了很多基础技术之后才能达到这个水平。今天要见到的基于接口的编程,有一个很大的好处就是可以避免类型转换,因为之前的方法都有大量的.NET和Matlab类型进行转换,基础不扎实的朋友很容易搞混淆。而基于接口的编程,则可以避免很多问题,但同时也对基础提出了更高的要求,要对接口定义,作用,以及方法多态等面向对象的特性更加了解。

下面截图是在Matlab帮助的说明:

回到目录

2.Type-Safe Interfaces简单说明

与直接编译为.NET程序集的要求不同,使用这项技术对.NET程序员的要求小很多,只需要很少的Matlab知识,但要对.NET技术精通,

之前由于Matlab的数据类型和.NET的基本数据类型不兼容,所以为了使得Matlab和.NET程序进行数据通信,就需要使用下面的技术:

1)Marshal data from .NET input data to a deployed function by creating an MWArray object from native .NET data.

The public functions in a deployed component return MWArray objects. 2)Marshal the output MATLAB data in an MWArray into native .NET data by calling one of the MWArray marshaling methods (ToArray(), for example).

所以使用传统的混编方式,又很多数据类型转换的过程。而在使用Type-Safe Interfaces技术后,这些中间过程都可以忽略,

只需要关系输入的.NET类型以及输出的.NET类型结果,Matlab会对数据进行内部的转换处理。可以看看前后2副图的对比:

因此,我们可以很明显的看到Type-Safe Interfaces带来的优势:

You avoid training and coding costs associated with teaching end users to work with MWArrays.

You minimize cost of data you must marshal by either placing MWArray objects in type-safe interfaces or by calling MWArray-based functions in the deployed component.

Flexibility — you mix type-safe interfaces with manual data marshaling to accommodate data of varying sizes and access patterns.

For example, you may have a few large data objects (images, for example) that would incur excess cost to your organization if managed

with a type-safe interface. By mixing type-safe interfaces and manual marshaling, smaller data types can be managed

automatically with the type-safe interface and your large data can be managed on an as-needed basis.

回到目录

3.Type-Safe Interfaces实际案例

对这个混编方式,很显示可以节省很多事情,我认为,作为原始的数据类型转换方式,还是应该掌握的。在掌握了之后,再使用这个方法,会事半功倍,毕竟不是所有的问题都可以用接口解决。接下来,就让我们一起用一个小的编程实例,来演示整个过程的使用。 演示环境:Visual Studio 2010,Matlab 2012a,.NET 4.0 演示内容:一个简单的乘法运算混编实现

一、新建一个 类库类型的项目 ,名称MatlabDemo,.NET 4.0,如下图所示:

一、在上面的项目中添加一个接口文件IMultiply.cs,并编写下面的代码,因为我们实现的是一个简单的乘法,所以添加如下几个接口方法:

1namespace MatlabDemo 2 {

3///

乘法接口 4publicinterface IMultiply 5 {

6//2个数直接相乘

7double multiply(double x, double y); 8

9//数组相乘

10double[] multiply(double[] x, double y); 11

12//矩阵相乘

13double[,] multiply(double[,] x, double[,] y); 14 }

15 }

这里注意,一定要将接口的可访问性设置为Public,否则混编的时候,Matlab会找不到接口原型,编译失败。编写好,编译项目即可,会在bin文件夹下得到MatlabDemo.dll文件,这个文件下面的步骤会用到。

三、编写M函数,并设置混编项目。我们编写一个简单的乘法M函数m,如下所示:

1 function z = multiply(x, y) 2

3 z = x * y;

注意这里的名称一定要和接口方法的名称对于起来,否则Matlab怎么会认识,想想就明白了。然后在Matlab中输入deploytool命令,输入项目名称:TypeSaftDemo,并选择项目类型:.NET Assembly,这个过程是“混编三部曲”基本过程,以前的视频中专门见到了,不仔细说明,如下图所示:

确定之后,混编项目基本就建立了,然后新建一个类DemoTest,并把上面编写的multiply.m函数添加到这个类中去,这其实就是一个常规的混编过程,很简单。添加完成

之后,如果是普通的混编方式,直接编译就可以了,但基于接口的混编方式,还有一个过程要设置,看下图,单击混编项目的设置(Settings...):

如下图,打开设置后,选择“Type Safe API”选项卡:

首先,选择我们在第一个过程中编写好的MatlabDemo.dll接口文件,选择后,程序会自动搜索该dll中的可用接口(公开的),在.NET interface下拉列表中显示,选择你需要的,这里我们是IMultiply,如下图所示的MatlabDemo.IMultiply,然后选择该接口和Matlab混编程序中对于的类,我们的multiply.m函数在DemoTest类中,如下图的Wrapped class:

设置完成之后,关闭即可。然后编译,如果没有问题,提示编译成功之后,打开编译好的文件夹,我们可以看到如下3个dll文件:

生成的3个文件,TypeSafeDemo.dll其实和普通的混编方式是一样的,可以和以前数据类型转换的方式一样使用;而DemoTestIMultiply.dll和TypeSafeDemoNative.dll这2个

一起使用,Matlab已经在内部将数据转换过程封装好了,直接使用即可。第一种方式就不演示了,直接演示如何用接口来计算乘法。

五、C#调用混编好的dll计算结果。在上一节中我们已经说明了几个dll的作用,下面将演示他们的用法,将DemoTestIMultiply.dll和TypeSafeDemoNative.dll一起复制到测试项目的C#项目中去(新建一个控制台测试项目),分别添加这几个dll的引用:MWAarray.dll和DemoTestIMultiply.dll以及TypeSafeDemoNative.dll。然后添加命名空间,具体核心代码如下所示:

1using System;

2using System.Collections.Generic; 3using System.Linq; 4using System.Text; 5

6using MathWorks.MATLAB.NET.Arrays; 7using MathWorks.MATLAB.NET.Utility; 8

9using TypeSaftDemo; 10

11namespace TypeSaftTest 12 {

13class Program 14 {

15staticvoid Main(string[] args) 16 {

17//混编接口类的实例化

18 DemoTestIMultiply di = new DemoTestIMultiply(); 19double[,] a = newdouble[2,2] {{1,2},{3,4} };

20double[,] b = newdouble[2, 2] { { 6, 7 }, {8, 9 } }; 21//分别演示接口的3种不同调用 22var t1 = di.multiply(3, 5);

23var t2 = di.multiply(newdouble[] { 1, 2, 3 }, 5); 24var t3 = di.multiply(a, b);

25 Console.WriteLine(\个数直接相乘:\+t1.ToString()); 26 Console.Write(\数组与单个数直接相乘:\);

27foreach (var item in t2 ) Console.Write(item.ToString()+\); 28 Console.WriteLine();

29 Console.Write(\矩阵乘法:\);

30foreach (var item in t3) Console.Write(item.ToString() + \); 31 Console.ReadKey (); 32 } 33 } 34 }

结果如下图所示:

上面就是Matlab和C#基于接口的混合编程的详细过程,混编是一个很有用的工具,但要用好,其实真的很难,接触混编这么长的时间以来,碰到过很多同学使用这个工具,绝大部分是误用,导致无故的工作量。要想混编成为自己工作和学习的得力助手,必须加强Matlab和.NET基础的学习,只有2者的基础掌握好了,足够熟悉这2个平台,你才可能更顺利的解决混编过程中遇到的问题。当混编出了问题的时候,需要很多经验才能度过难关,这一点很重要,不要指望学会这个过程,就可以解决所有问题。期待Mathworks公司对Matlab的混编编程支持越来越强大。

【原创】Matlab.NET混合编程技巧之直接调用Matlab内置函数

1.传统的Matlab.NET混合编程步骤

传统的Matlab.NET混合编程有2种方式:

1)Matlab编写好M函数,利用deploytool编译m函数生成dll,在C#项目中引用并调用;

2)基于接口的编写方式,也是利用deploytool工具,过程繁琐一点,对编程人员素质要求高一点,但不需要进行繁琐的数据类型转换。我的博客有一篇文章专门介绍了这个混合编程方式,也有例子,大家有兴趣的可以看看:

http://www.cnblogs.com/asxinyu/archive/2013/05/16/3082299.html 不管上面用哪种方式,Matlab和C#混编的基本步骤,大概都是下面的过程:

1) 编写M函数,并首先在Matlab中测试是正确可以调用的。注意命名规范,注释规范; 2) 使用命令打开 deploytool工具,设置项目名称,选择类型:.NET Assembly,然后新建一个类,并添加编写好的M函数

3) 编译,生成dll,并在C#项目中添加引用(还需要引用对应版本的MWArray),利用对象浏览器查看生成dll的方法结构,并根据Matlab和C#的类型转换规则,进行数据转换即可, 如果是接口的编程,这个过程相对要简单。

回到目录

2.深入解析传统混编所生成的代码

2.1 第一步:编写M函数,并测试可以使用

为了好我们今天的目的相匹配,特意封装一个简单的内置函数,plot,来画一个简单的图形,如下所示M函数

1 function PlotTest(n)

2 %编写一个简单的函数,对plot进行简单封装一下 3 plot(1:n,1:n);

4 %测试正确,才可以进行下一步工作

注意,混编必须是m函数function的形式才能被调用。上述函数简单测试一下,没有问题(复杂的函数一定要多测试,否则后续调试非常困难)。继续下一步。

2.2 第二步:在Matlab中使用deploytool建立混编项目

在Matlab工作区输入命令:deploytool,然后得到下面界面,输入混编项目的名称,选择存储位置,关键的是类型那里一定要选择\。如下图所示:

选择“OK”之后,下一步matlab界面右侧会出现项目解决方案,需要添加类名称和M文件。这个类名称,就是编译完成之后C#项目中的类对象名称,然后添加我们刚才上一步编写的“PlotTest.m”,然后编译即可,如下图所示:

到此为止,一个常规 简单的Matlab.NET混编已经完成了60%了。编译完成之后,打开“Package”选项卡,即可看到生成的dll文件,然后点击右键,打开文件夹即可,如下图所示:

2.3 查看混编生成的代码

这个过程很关键,其实包含很多信息,只不过95%以上的人都没有注意到其实混编生成的dll是有源文件的,通过查看源文件就应该知道混编的原理,只不过这是matlab自动生成 而已。那看看生成的源码吧。

打开Matlab混编项目的目录,可以看到有2个文件夹,\”,“src”2个文件夹。\文件夹就是上面图中生成的dll,注意有2个dll,1个是“项目名称.dll”,一个

是“项目名称Native.dll”,这2个dll的差别可以通过\文件夹源码来观察。“distrib”就是源代码的文件夹。如下图所示,src文件夹的文件示意图:

我们2.2中新建的类名是TestDemo,所以生成的的源码名称也是TestDemo,看看这2个cs文件中的代码,同时类的方法也可以在VS中通过对象浏览器来查看dll有哪些方法以及方法的参数类型。直接贴这2个cs文件的代码,顺便解释和对比下: TestDemo.cs文件源码:

1/*

2* MATLAB Compiler: 4.17 (R2012a) 3* Date: Mon Sep 09 16:19:01 2013

4* Arguments: \\ 5* \

\

6* \ 7* \\ 8* \

\\ 9*/

10using System;

11using System.Reflection;

12using System.IO;

13using MathWorks.MATLAB.NET.Arrays; 14using MathWorks.MATLAB.NET.Utility; 15

16#if SHARED

17 [assembly: System.Reflection.AssemblyKeyFile(@\)] 18#endif 19

20namespace PlotTest 21 { 22

23///

24/// The TestDemo class provides a CLS compliant, MWArray interface to the M-functions

25/// contained in the files: 26///

27/// D:\\Work\\DevelopMent_SVN\\Matlab\\MatlabBlog\\PlotTest.m 28/// 29/// deployprint.m

30/// 31/// printdlg.m 32///

33///

34/// @Version 0.0 35///

36publicclass TestDemo : IDisposable 37 {

38#region Constructors 39

40///

41/// The static constructor instantiates and initializes the MATLAB Compiler Runtime 42/// instance. 43///

44static TestDemo() 45 {

46if (MWMCR.MCRAppInitialized) 47 {

48 Assembly assembly= Assembly.GetExecutingAssembly(); 49

50string ctfFilePath= assembly.Location; 51

52int lastDelimiter= ctfFilePath.LastIndexOf(@\); 53

54 ctfFilePath= ctfFilePath.Remove(lastDelimiter, (ctfFilePath.Length - lastDelimiter)); 55

56string ctfFileName = \; 57

58 Stream embeddedCtfStream = null; 59

60 String[] resourceStrings = assembly.GetManifestResourceNames(); 61

62foreach (String name in resourceStrings) 63 {

64if (name.Contains(ctfFileName)) 65 {

66 embeddedCtfStream =

assembly.GetManifestResourceStream(name); 67break;

68 } 69 }

70 mcr= new MWMCR(\,

71 ctfFilePath, embeddedCtfStream, true); 72 } 73else 74 {

75thrownew ApplicationException(\initialized\); 76 } 77 } 78 79

80///

81/// Constructs a new instance of the TestDemo class. 82///

83public TestDemo() 84 { 85 } 86 87

88#endregion Constructors 89

90#region Finalize 91

92///

93/// Class destructor called by the CLR garbage collector.

94///

95 ~TestDemo() 96 {

97 Dispose(false); 98 } 99 100

101///

102/// Frees the native resources associated with this object 103///

104publicvoid Dispose() 105 {

106 Dispose(true); 107

108 GC.SuppressFinalize(this); 109 } 110 111

112///

115protectedvirtualvoid Dispose(bool disposing) 116 {

117if (!disposed) 118 {

119 disposed= true; 120

121if (disposing) 122 {

123// Free managed resources; 124 } 125

126// Free native resources 127 } 128 } 129 130

131#endregion Finalize 132

133#region Methods 134

135///

136/// Provides a void output, 0-input MWArrayinterface to the PlotTest M-function.

137///

138///

139/// M-Documentation:

140/// 编写一个简单的函数,对plot进行简单封装一下 141/// 142///

143publicvoid PlotTest() 144 {

145 mcr.EvaluateFunction(0, \, new MWArray[]{}); 146 } 147 148

149///

150/// Provides a void output, 1-input MWArrayinterface to the PlotTest M-function.

151///

152///

153/// M-Documentation:

154/// 编写一个简单的函数,对plot进行简单封装一下 155///

156/// 157///

158publicvoid PlotTest(MWArray n) 159 {

160 mcr.EvaluateFunction(0, \, n); 161 } 162 163

164///

165/// Provides the standard 0-input MWArray interface to the PlotTest M-function.

166///

167///

168/// M-Documentation:

169/// 编写一个简单的函数,对plot进行简单封装一下 170///

171///

172///An Array of length \173/// arguments. 174///

175public MWArray[] PlotTest(int numArgsOut) 176 {

177return mcr.EvaluateFunction(numArgsOut, \, new MWArray[]{}); 178 } 179 180

181///

182/// Provides the standard 1-input MWArray interface to the PlotTest M-function.

183///

184///

185/// M-Documentation:

186/// 编写一个简单的函数,对plot进行简单封装一下 187///

188///

189///

190///An Array of length \191/// arguments. 192///

193public MWArray[] PlotTest(int numArgsOut, MWArray n) 194 {

195return mcr.EvaluateFunction(numArgsOut, \, n); 196 } 197 198 199

200///

201/// This method will cause a MATLAB figure window to behave as a modal dialog box.

202/// The method will not return until all the figure windows associated with this

203/// component have been closed. 204///

205///

206/// An application should only call this method when required to keep the

207/// MATLAB figure window from disappearing. Other techniques, such as calling 208/// Console.ReadLine() from the application should be considered where 209/// possible. 210///

211publicvoid WaitForFiguresToDie() 212 {

213 mcr.WaitForFiguresToDie();

214 } 215 216 217

218#endregion Methods 219

220#region Class Members 221

222privatestatic MWMCR mcr= null; 223

224privatebool disposed= false; 225

226#endregion Class Members 227 } 228 }

TestDemoNative.cs文件源码:

1/*

2* MATLAB Compiler: 4.17 (R2012a) 3* Date: Mon Sep 09 16:19:01 2013

4* Arguments: \\ 5* \

\

6* \ 7* \\ 8* \

\\ 9*/

10using System;

11using System.Reflection; 12using System.IO;

13using MathWorks.MATLAB.NET.Arrays; 14using MathWorks.MATLAB.NET.Utility; 15

16#if SHARED

17 [assembly: System.Reflection.AssemblyKeyFile(@\)] 18#endif

19

20namespace PlotTestNative 21 { 22

23///

24/// The TestDemo class provides a CLS compliant, Object (native) interface to the

25/// M-functions contained in the files: 26///

27/// D:\\Work\\DevelopMent_SVN\\Matlab\\MatlabBlog\\PlotTest.m 28/// 29/// deployprint.m

30/// 31/// printdlg.m 32///

33///

34/// @Version 0.0 35///

36publicclass TestDemo : IDisposable 37 {

38#region Constructors 39

40///

41/// The static constructor instantiates and initializes the MATLAB Compiler Runtime 42/// instance. 43///

44static TestDemo() 45 {

46if (MWMCR.MCRAppInitialized) 47 {

48 Assembly assembly= Assembly.GetExecutingAssembly(); 49

50string ctfFilePath= assembly.Location; 51

52int lastDelimiter= ctfFilePath.LastIndexOf(@\); 53

54 ctfFilePath= ctfFilePath.Remove(lastDelimiter, (ctfFilePath.Length - lastDelimiter)); 55

56string ctfFileName = \; 57

58 Stream embeddedCtfStream = null; 59

60 String[] resourceStrings = assembly.GetManifestResourceNames(); 61

62foreach (String name in resourceStrings) 63 {

64if (name.Contains(ctfFileName)) 65 {

66 embeddedCtfStream =

assembly.GetManifestResourceStream(name); 67break;

68 } 69 }

70 mcr= new MWMCR(\,

71 ctfFilePath, embeddedCtfStream, true); 72 } 73else 74 {

75thrownew ApplicationException(\initialized\); 76 } 77 } 78 79

80///

81/// Constructs a new instance of the TestDemo class. 82///

83public TestDemo() 84 { 85 } 86 87

88#endregion Constructors 89

90#region Finalize 91

92///

93/// Class destructor called by the CLR garbage collector. 94///

95 ~TestDemo() 96 {

97 Dispose(false); 98 } 99 100

101///

102/// Frees the native resources associated with this object 103///

104publicvoid Dispose() 105 {

106 Dispose(true); 107

108 GC.SuppressFinalize(this); 109 } 110 111

112///

115protectedvirtualvoid Dispose(bool disposing) 116 {

117if (!disposed) 118 {

119 disposed= true; 120

121if (disposing) 122 {

123// Free managed resources; 124 } 125

126// Free native resources 127 } 128 } 129 130

131#endregion Finalize 132

133#region Methods 134

135///

136/// Provides a void output, 0-input Objectinterface to the PlotTest M-function.

137///

138///

139/// M-Documentation:

140/// 编写一个简单的函数,对plot进行简单封装一下 141/// 142///

143publicvoid PlotTest()

144 {

145 mcr.EvaluateFunction(0, \, new Object[]{}); 146 } 147 148

149///

150/// Provides a void output, 1-input Objectinterface to the PlotTest M-function.

151///

152///

153/// M-Documentation:

154/// 编写一个简单的函数,对plot进行简单封装一下 155///

156/// 157///

158publicvoid PlotTest(Object n) 159 {

160 mcr.EvaluateFunction(0, \, n); 161 } 162 163

164///

165/// Provides the standard 0-input Object interface to the PlotTest M-function.

166///

167///

168/// M-Documentation:

169/// 编写一个简单的函数,对plot进行简单封装一下 170///

171///

172///An Array of length \173/// arguments. 174///

175public Object[] PlotTest(int numArgsOut) 176 { 177return mcr.EvaluateFunction(numArgsOut, \, new Object[]{}); 178 } 179 180

181///

182/// Provides the standard 1-input Object interface to the PlotTest M-function.

183///

184///

185/// M-Documentation:

186/// 编写一个简单的函数,对plot进行简单封装一下 187///

188///

189///

190///An Array of length \191/// arguments. 192///

193public Object[] PlotTest(int numArgsOut, Object n) 194 {

195return mcr.EvaluateFunction(numArgsOut, \, n); 196 } 197 198

199///

200/// Provides an interface for the PlotTest function in which the input and output

201/// arguments are specified as an array of Objects. 202///

203///

204/// This method will allocate and return by reference the output argument

205/// array. 206/// M-Documentation:

207/// 编写一个简单的函数,对plot进行简单封装一下 208///

209///

210/// 211/// 212///

213/// arguments 214///

215 [MATLABSignature(\, 1, 0, 0)] 216protectedvoid PlotTest(int numArgsOut, ref Object[] argsOut, Object[] argsIn, params Object[] varArgsIn) 217 {

218 mcr.EvaluateFunctionForTypeSafeCall(\, numArgsOut, ref argsOut, argsIn, varArgsIn); 219 } 220

221///

222/// This method will cause a MATLAB figure window to behave as a modal dialog box.

223/// The method will not return until all the figure windows associated with this

224/// component have been closed. 225///

226///

227/// An application should only call this method when required to keep the

228/// MATLAB figure window from disappearing. Other techniques, such as calling 229/// Console.ReadLine() from the application should be considered where 230/// possible. 231///

232publicvoid WaitForFiguresToDie() 233 {

234 mcr.WaitForFiguresToDie(); 235 } 236 237 238

239#endregion Methods 240

241#region Class Members 242

243privatestatic MWMCR mcr= null; 244

245privatebool disposed= false; 246

247#endregion Class Members 248 } 249 }

对比大家就可以发现,只不过一个更加傻瓜化,参数都是Object了,其实这样反而不好,增加了类型转换的代价,如果知道,为何不给一个正确的给他呢。关于这2个dll的速度,曾经听说过是有差别的,博客园有人给过测试,我没实际测试过,还是习惯用传统的TestDemo.cs,因为参数类型都是Object,不直观,出了问题也有点头疼。

2.4 上述Matlab自动生成代码的要点

后面某些类或者方法的XML注释就不说了,自动生成的东西,可以对照M文件的注释来看。

1.首先看第一段的注释信息:

1/*

2* MATLAB Compiler: 4.17 (R2012a) 3* Date: Mon Sep 09 16:19:01 2013

4* Arguments: \\ 5* \

\

6* \ 7* \\ 8* \

\\ 9*/

10using System;

11using System.Reflection; 12using System.IO;

13using MathWorks.MATLAB.NET.Arrays; 14using MathWorks.MATLAB.NET.Utility;

上面这段信息主要是说明当前Matlab编译器的版本,因为编译的版本和部署的MCR版本必须对应起来,否则是不能运行的。然后有编译日期,以及编译的参数,类名以及M函数的地址等信息,其实知道这些参数,理论上是可以自己在程序里面调用Matlab的编译器进行编译工作的,只不过比较复杂,能力有限,研究不下去。下面的引用大家应该明白,这个是MWArray.dll里面的命名空间,所以混编的项目都要引用对应版本的MWArray.dll

2.关键的静态构造函数

1static TestDemo() 2 {

3if (MWMCR.MCRAppInitialized) 4 {

5 Assembly assembly= Assembly.GetExecutingAssembly(); 6string ctfFilePath= assembly.Location;

7int lastDelimiter= ctfFilePath.LastIndexOf(@\);

8 ctfFilePath= ctfFilePath.Remove(lastDelimiter, (ctfFilePath.Length - lastDelimiter)); 9string ctfFileName = \;

10 Stream embeddedCtfStream = null; 11 String[] resourceStrings = assembly.GetManifestResourceNames();

12foreach (String name in resourceStrings) 13 {

14if (name.Contains(ctfFileName)) 15 {

16 embeddedCtfStream =

assembly.GetManifestResourceStream(name); 17break;

18 } 19 }

20 mcr= new MWMCR(\,ctfFilePath, embeddedCtfStream, true); 21 } 22else

23 {

24thrownew ApplicationException(\initialized\); 25 } 26 }

如果有一些C#的开发和编程经验看上面的代码问题应该不大,否则还真有点难说清楚,简单的说几个要点:

1)这个构造函数的作用主要是检测MCR对象是否初始化,如果没有,则寻找程序集,并拼接资源的位置,正确进行初始化

2) 上面的ctf其实是包含在dll程序集里面的,以资源的形式,这个文件是核心,它才真正的包括了Matlab编译之后的,MCR可以运行的中间程序。

3) 必须要合法正确的ctf文件和dll文件才能 正确的初始化mcr对象,合法的意思,是Matlab内部有校验机制,包括对相关版本,在以前的版本生成文件中,很明显,现在2012a里面都隐藏起来了,不过要求都一样。

4) 上面方法其实已经间接的告诉了我们怎么初始化mcr对象,有了mcr对象,一切都好办了,因为它才是MCR的核心。

3.PlotTest封装的方法代码

1publicvoid PlotTest() 2 {

3 mcr.EvaluateFunction(0, \, new MWArray[]{}); 4 }

5publicvoid PlotTest(MWArray n) 6 {

7 mcr.EvaluateFunction(0, \, n); 8 }

9public MWArray[] PlotTest(int numArgsOut) 10 { 11return mcr.EvaluateFunction(numArgsOut, \, new MWArray[]{}); 12 }

13public MWArray[] PlotTest(int numArgsOut, MWArray n) 14 {

15return mcr.EvaluateFunction(numArgsOut, \, n); 16 }

看了字段代码,再对应mcr的初始化,其实都很明朗了。通过mcr的EvaluateFunction来调用M函数。上面的代码有几个重载方法,可以实用很多不同的情况,有时候,这些方法的个数会更多,其实没多大必要,也可以自己编译一下,把没用的删掉,保留少数几个有用的即可。同时也可以看到,这里直接通过字符串来传递函数名称的,因此必须保证这个函

数能被mcr搜索到。比如我们这里的\这个函数其实就包含了ctf文件中(注意ctf文件是可以和dll分开的,在混编项目里可以设置)。

回到目录

3.上述代码到内置函数的调用

上述已经讲解了整个mcr调用的过程,其实就是通过mcr的EvaluateFunction来调用M函数,但要保证对于的函数名称在mcr搜索的范围内。那么我们是不是可以假设:内置函数都在MCR内部,应该是可以搜索到的,那么把上面的函数名称换一下,是不是也是可行的。这个假设也是我最早接触时候的想法,有了假设,当然要去验证。现在看来这个当然是肯定的,那么不妨重新演示一遍。过程不详细讲了,代码也有注释,混编要引用的MWArray.dll和命名空间也不提了,看代码:

1using System;

2using System.Collections.Generic; 3using System.Linq; 4using System.Text;

5using System.Reflection; 6using System.IO; 7

8using MathWorks.MATLAB.NET.Utility; 9using MathWorks.MATLAB.NET.Arrays; 10 11

12namespace BuildInFunctionDemo 13 {

14class Program 15 {

16static MWMCR mcr;

17staticvoid Main(string[] args) 18 {

19#region 首先使用PlotTest.dll来初始化mcr,因为这个dll是混编“合法”产生的,只有这样才能顺利启动mcr

20if (MWMCR.MCRAppInitialized) 21 {

22string path = Path.Combine(System.Environment.CurrentDirectory, \);

23 Assembly assembly = Assembly.LoadFile(path); 24string ctfFilePath = assembly.Location;

25int lastDelimiter = ctfFilePath.LastIndexOf(@\);

26 ctfFilePath = ctfFilePath.Remove(lastDelimiter, (ctfFilePath.Length - lastDelimiter)); 27string ctfFileName = \;

28 Stream embeddedCtfStream = null; 29 String[] resourceStrings = assembly.GetManifestResourceNames(); 30

31foreach (String name in resourceStrings) 32 {

33if (name.Contains(ctfFileName)) 34 {

35 embeddedCtfStream = assembly.GetManifestResourceStream(name); 36break;

37 } 38 }

39 mcr = new MWMCR(\,ctfFilePath, embeddedCtfStream, true);

40 } 41else

42 {

43thrownew ApplicationException(\initialized\); 44 } 45#endregion 46

47#region 直接调用混编dll中的封装函数进行测试

48 mcr.EvaluateFunction(0, \, 5); 49

50//注意这里要断点调试才能看到效果哦,因为mcr会把图绘制在一个Figure上面,

51//后面的会覆盖前面的,这里暂停一下,可以看前面的效果 52//下面就是直接调用matlab的plot函数的效果

53 MWNumericArray x = newdouble[]{1,2,3,4,5};

54 MWNumericArray y = newdouble[]{2,1,2.8,5.3,4.7}; 55 mcr.EvaluateFunction(0, \,x,y ); 56#endregion

57

58 Console.ReadKey(); 59 } 60 } 61 }

唯一要注意的就是50-52的说明,要加断点看2次绘制的效果。分别截图如下:

= 回到目录

4.总结

抛砖引玉,这里只是一个思路,附代码下载吧。

Multiple Inputs and Outputs in Builder NE Type Safe APIs

Posted by Loren Shure, June 30, 2011 Guest blogger Peter Webb returns with another in an occasional series of postings about application deployment. Contents ? ? ? ? Multiple Arguments with Varying Types

Overloaded Functions and Parameter Order in a C# Interface Building and Running the Example Flexibile or Complicated? Multiple Arguments with Varying Types I've got a MATLAB function with multiple inputs and outputs that I'd like to call from C#. Though that may not seem like much of a challange, MATLAB processes function arguments very differently from C#, particularly optional arguments and multiple return values. The behavior of my MATLAB function, polygonal, depends on both the number and types of the inputs. polygonal computesthree different number sequences. Given an integer N for each sequence, it returns the Nth entry in each sequence. Only the first input (tN) is required; the other two are optional. function [t, p, h] = polygonal(tN, pN, hN) In typical MATLAB fashion, if any input is a vector of length K, polygonal returns K elements of that sequence. For each sequence, the numeric type of the input determines the numeric type of the output. If tN is int32, for example, polygonalreturns an int32 t. That's a lot of complexity wrapped up in a single function line. I count at least 36 different ways to call polygonal. How do we manage this complexity in C#? In a word: overloading. Overloaded Functions and Parameter Order in a C# Interface Generally speaking, a function is overloaded if you can call it with different numbers or types of inputs and outputs. In C#, you must write a new function for each set of inputs and outputs. I've implemented five of polygonal's 36 overloads in C# to demonstrate how Builder NE matches C# function declarations to MATLAB functions. The simplest of polygonal's overloads consists of one scalar double input and one scalar double output. In C#: double polygonal(double t); Builder NE maps the first C# input, t to the first MATLAB input (tN, and note the names of the arguments are not considered in the matching process), and the first MATLAB output (t) to the C# function's return value.

Next, I'll declare a function to call polygonal with three scalar inputs, which produces three scalar outputs. Since C# does not permit multiple return values, Builder NE supports C# out parameters in their place. void polygonal(out double t, out double p, out double h, double tN, double pN, double hN); In this function, the outputs appear first, followed by the inputs, and the return type is void. This form is perhaps closest to the structure of the MATLAB function, but Builder NE supports many others. You may map the first MATLAB output to the C# function's return value:

double polygonal(out double p, out double h, double tN, double pN, double hN); out t has vanished, and the return type changed from void to double.

You may also interleave (mix) inputs and outputs. Here, I've placed each input before the output it produces:

void polygonal(double tN, out double t, double pN, out double p, double hN, out double h); Finally, remember that polygonal supports vector inputs and and outputs; here I've requested double[] vector outputs from from double[] vector inputs. In this function the outputs again appear before the inputs, as that's the style I prefer. void polygonal(out double[] t, out double[] p, out double[] h, double[] tN, double[] pN, double[] hN); Building and Running the Example

First, download the source code for this article from MATLAB Central.

As usual, the process of invoking polygonal through a type safe API consists of three steps: ? Build the IFigurate interface DLL.

? Create the Generator .NET assembly and the GeneratorIFigurate type safe interface. ? Compile the main program, PolySeq, after referencing IFigurate and GenerateIFigurate in the PolySeq project.

The file ReadmeParameters.txt contains detailed instructions. Make sure your runtime environment is set up correctly, and then

run PolySeq\\PolySeq\\bin\\Debug\\PolySeq.exe. It callspolygonal through several of the C# interfaces described above and produces the following output:

The 17th triangular number: 153 The 13th triangular number: 91 The 11th pentagonal number: 176 The 19th hexagonal number : 703 Polygonal Numbers N: 3 6 9 ----------------------- Triangular: 6 21 45 Pentagonal: 12 51 117 Hexagonal : 15 66 153 You can generate the same numbers in MATLAB with three calls to polygonal: % 17th triangular number t = polygonal(17); % 13th triangular, 11th pentagonal and 19th hexagonal numbers [t, p, h] = polygonal(13, 11, 19); % 3rd, 6th, and 9th triangular, pentagonal and hexagonal numbers order = [3, 6, 9]; [t, p, h] = polygonal(order, order, order); Flexibile or Complicated?

What do you think of the parameter ordering and function overloading rules? Some of them were dictated by the structure of C# and MATLAB, but some resulted from usability testing and our design judgement. Are they too complicated, or just flexible enough? Let me know here.

Introducing Type Safe APIs with Builder NE 8Posted by Loren Shure, June 3, 2011

Guest blogger Peter Webb returns with another in an occasional series of postings about application deployment.

Contents

? ? ? ? ?

Life is Too Short to Write Boring Code Type Safe APIs Example C# Code

Building and Running the Example More to Come

Life is Too Short to Write Boring Code

I can call MATLAB functions from C# using Builder NE. But MATLAB and C# have very different data types, so I spend a lot of time manually converting data from one system to the other. That kind of work is tedious and error-prone -- the C# compiler can't check to ensure that I'm passing the right type of data to my MATLAB functions.

Ideally, I'd like to be able to write MATLAB code that uses MATLAB data types and C# code that uses C# data types, and not have to worry about the conversion between them. Consider a very simple example, a MATLAB multiply function: function z = multiply(x, y) z = x * y; Though it looks simple, multiply behaves very differently depending on the type of its inputs. If the inputs are scalars, the result is a scalar, but if they are matrices, the result is the matrix product. And the numeric data type of the output (int32, double) varies with the type of the input.

In C#, I'd like to call multiply with scalars and matrices, and additionally to to support scalars times vectors. That's three ways to call multiply, and in C#, that means three separate functions: double multiply(double x, double y) // Scalar double[,] multiply(double[,] x, double[,] y) // Matrix double[] multiply(double[] x, double y) // Vector x Scalar So far, that's nothing new -- I can do this today. I write each of these multiply functions myself, filling them up with code that converts .NET scalars, vectors and arrays to MATLAB matrices and vice versa. But it's boring, and I hate being bored.

So instead, I turn to the type safe APIs generated by Builder NE (as of version 4.0, R2011a), and let Builder NE write this code for me.

Type Safe APIs

Type Safe APIs allow you to specify a kind of contract between your C# code and your MATLAB functions. You describe exactly what kind of data you want to pass back and forth between MATLAB and C#, and Builder NE generates functions for those types only. You give up a little flexiblity (you can't pass just any type of data to your MATLAB function, like you could with the MWArray-based interface), but you gain type safety. Now the C# compiler can tell if you're doing something you shouldn't be, like passing strings to a function that operates on integers. (While this often completes without error, it very seldom produces a useful result.)

In C#, the usual mechanism for establishing such a contract is an interface. An interface defines the names and input and output types of one or more functions, but provides no implemention. We can collect our

three multiply functions into the IMultiplyinterface. By convention, .NET interface names begin with a capitial I.

interface IMultiply { // Scalar multiplication double multiply(double x, double y); // Multiply vector by a scalar, return a vector double[] multiply(double[] x, double y); // Matrix multiplication double[,] multiply(double[,] x, double[,] y); } The interface uses function overloading to take advantage of the polymorphism of the MATLAB function. The functions in the C# interface have the same name as the MATLAB function; Builder NE matches interface functions to MATLAB functions by name and number of arguments. (I'll discuss the details of argument matching in a later article.) To use a type safe API, you'll need:

? ? ?

A MATLAB function

A C# interface that specifies the input and output types of that MATLAB function A C# program that calls the MATLAB function through the C# interface.

The example demonstrates how to incorporate a type safe API into a C# program. In the example, you'll work through 4 basic steps:

? Create a MATLAB function, multiply. ? Define a C# interface IMultiply.

? Compile multiply into a .NET component named Multiply and generate the type safe API MultiplyIMultiply.

? Develop a C# main program that calls multiply through the IMultiply interface.

Since we've already seen the MATLAB code and the C# interface, let's take a look at the C# main program.

Example C# Code

You invoke MATLAB functions from C# by calling the instance methods of a Builder NE-generated component. Builder NE names the type safe API class by combining the names of the MATLAB function component (Multiply) and the C# interface (IMultiply). In this case, MultiplyIMultiply is the name of the type safe API class. Call new to create an instance of the component's type safe API class: // Create an instance of the Multiply component's type safe API. IMultiply m = new Multiply.MultiplyIMultiply(); IMultiply publishes three multiply methods, one of which multiplies a vector and a scalar. Create the input data by declaring C# variables:

// Create a C# vector and a scalar. double[] v = new double[]{ 2.5, 81, 64 }; double s = 11; Finally, compute the product by calling multiply:

// Multiply the vector and the scalar. Note: all inputs and outputs // are native C# types. double[] d = m.multiply(v, s); As usual in C#, passing the wrong type of inputs (if v had been declared as a string for example) results in compile-time errors.

Building and Running the Example

Download the source code from MATLAB Central into a new directory. The download contains

the multiply MATLAB function and two Visual Studio projects. To create a runnable executable, you need to build the C# interface assembly, create adeploytool .NET assembly project for the MATLAB function and then link the main program against these two assemblies. The file ReadmeIntro.txt contains detailed instructions.

The downloaded files compile into Multiplier.exe, a C# program that calls each of the methods in the IMultiply interface and prints the results. Make sure your runtime environment is set up correctly (you need either the MCR or MATLAB'sruntime/ directory on your path) and then locate and run Multiplier.exe from a DOS command window. The output should look something like this: 17 * 3.14159 = 53.40703 [ 2.5 81 64 ] * 11 = [ 27.5 891 704 ] 8 1 6 8 1 6 91 67 67 3 5 7 * 3 5 7 = 67 91 67 4 9 2 4 9 2 67 67 91 To enable other types of multiplcation, say vector times matrix or matrix times scalar, define the appropriate methods inIMultiply and then regenerate the Multiply component.

More to Come

To keep this post from turning into a book, I've discussed only the simplest and most common uses of Builder NE's type safe APIs. Forthcoming articles will reveal the secrets of parameter ordering, address the use of structured types (cell arrays and structures), and demonstrate how type safe APIs enable interprocess communication through the Windows Communication Foundation.

In the meantime, please let me know what you think of this new feature. Will it make your job easier? How could we improve it even futher? Let us know here.

Get the MATLAB code

Published with MATLAB? 7.12

Category:

Deployment

? ? ? ? ? ? ?

Tweet

< Transferring Data Between Two Computers...

Calculating the Area Volume Under... > You can follow any comments to this entry through the RSS 2.0 feed. Both comments and pings are currently closed.

8 CommentsOldest to Newest

Alexandre Kozlov replied on June 3rd, 2011 6:23 pm UTC :1 of 8

Isn’t it possigble just to introduce a datatypes for MatLab variables? With – for backward compatibility – a generic default type (like Variant in VBA). This will help MathWorks to implement a lot of another features to resolve a lot of my problems like:

1. Auto code completion. Espetially with my own classes – I’d like to see all methods of the corresponding class after typing a variable name followed by a dot.

2. Auto doc generation. Espetially for dependency reports (today it’s impossible to know what class will be passed as a parameter for my function).

3. Methods overloading. Often I’d like to have two methods – just like in your exemple, the same name, the same parameters, but depending of their types, I want to write different function’s bodies. Today I have to write myself a function’s header to determine a case I’m in, and to call one of more specific functions (with strange names instead of the same name – as they do the same thing). 4. Etc., etc.

Joan replied on June 4th, 2011 6:02 pm UTC :2 of 8 Hi,

That sounds really interesting. Any hope to get something similar for Java? Joan

Ben Schmitt replied on June 6th, 2011 1:55 pm UTC :3 of 8

The new feature looks very useful for our applications, I look forward to reading more about it.

I also couldn’t agree more with Alexandre, it would be attractive to have the option of type-explicit m-code, equivalent to VBA’s “Option Explicit”.

Peter Webb replied on June 6th, 2011 5:10 pm UTC :4 of 8 Joan,

We’re definitely thinking about it. But I can’t say that we’ll do it, or if we do, when it might ship. :-)

Peter Webb replied on June 6th, 2011 5:15 pm UTC :5 of 8 Alexandre and Ben,

We’ve been thinking about this for at least a decade, but haven’t come up with a good design yet. It’s a real challenge balancing the ease-of-use and performance trade-offs. For now, the deployment tools are going to limit themselves to managing types at the interface between MATLAB and external execution environments like Microsoft .NET.

owr replied on June 6th, 2011 11:25 pm UTC :6 of 8

Thanks for the example – I am really enjoying the new features in Builder NE. I would love to see some good examples of using the MWObjectArray coupled with .NET External Interfaces to deploy MATLAB functions that return custom C# objects.

Peter Webb replied on June 7th, 2011 3:49 pm UTC :7 of 8

owr,

The type safe APIs will allow you to return custom C# structures from MATLAB functions. (The C# field names have to match the MATLAB field names.) Objects are trickier, because they have methods.

What exactly are you looking for? Automatic generation of a C# object that acts as a proxy for a MATLAB object? Automatic initialization of a C# object from a MATLAB structure? Or something else entirely?

Patrick replied on September 6th, 2011 10:13 am UTC :8 of 8 Loren, Peter,

Good to see that you are improving the Matlab Builder NE.

Conversion of data between Matlab and C# causes a lot of programming and maintenance overhead in our application, so I would love to use the new Type-Safe API.

I’ve tried the Type-Safe API creation to see if we could use it in our application. Some comments:

* Automatic conversion is supported for structs, not objects. Unfortunately this does not lead to a workable solution for us: Structs are not preferred in due to their limitations (eg. being sealed).

* The DeployTool can only generate one TypeSafeAPI per project. We have separated our interface with Matlab into 4 classes. It appears that for this to work we would have to split our interface into 4 seperate assemblies, and 4 TypeSafeAPI assemblies.

Because of the above reasons we will not yet use the TypeSafeAPI functionality. However, using the new Builder NE provides two good additions for us: * the method MWArray.ConvertToNativeTypes() * the MwObjectArray

In the past we have created our own data conversion utilities to maintain readability of our calls to Matlab, and create reusable wrapping code.

These utilities use reflection to map custom .Net objects to MwStructArrays. Due to the above mentioned two additions we were already able to reduce the code for our own conversion utilities by 50%! Hope to see more of these improvements in future releases!

These postings are the author's and don't necessarily represent the opinions of MathWorks.

%% Multiple Inputs and Outputs in Builder NE Type Safe APIs % Guest blogger

% returns with another in an

%

本文来源:https://www.bwwdw.com/article/qvlw.html

Top