using matlab from a c#

10
Using Matlab from a C# application. During writing application for my Masters degree diploma I wrote simple application t was using COM Matlab server. I have found hard to using it mainly to lack of documentation which is really basic with only few code e!amples for C#. I guess writing programs that use Matlab for calculating is not encouraged by Math"orks you would became competition that way . onetheless I accomplished why I have re$uired to do so I decided to share this with rest of the world. Important: I was using %&'('a version of Matlab. I reali)e that there is newer versio *ut I had only this version at my disposal. +ince interface for communicating with Matlab server is dependent of installed Matlab version and registry entries it may ha been di,erent with yours. *ut I suspect not to much. I also tries with -.( and if I remember correctly/ it re$uired only to swap reference in 0isual +tudio. *ut again... was only test so there might be other problems that I am not aware of. 1et2s start with simple console application. 1ets call it Matlab3est. 4irst we will a reference with COM interface. Click %M* on pro5ect and choose 67dd %eference8 option. In new window click COM tab. In search te!t bo! write 2Matlab2. 3hen choose 9Matlab 7pplication 0ersion -.('/ 3ype 1ibrary9. :ou should get new reference like below; <reat. ow we should test if it is working. In order to use it we should create our M server from C# application. 3o that we can add code to our main program; =ide Copy Code var activationConte!t > 3ype.<et3ype4rom?rogID 9matlab.application.single9 /@ var matlab > M17pp.M17pp/7ctivator.CreateInstance activationConte!t/@ Console."rite1ine matlab.A!ecute 9(B&9//@ Console.%ead ey /@ 3his code will create single Matlab COM server through 7ctivator class. ?rogram Id 9matlab.application.single9 means single Matlab COM server for our application. "hen will try to create another Matlab it will 5ust return reference to the same ob5ect.

Upload: saurav-keshri

Post on 02-Nov-2015

251 views

Category:

Documents


1 download

DESCRIPTION

matlab

TRANSCRIPT

Using Matlab from a C# application.During writing application for my Masters degree diploma I wrote simple application that was using COM Matlab server. I have found hard to using it mainly to lack of documentation, which is really basic with only few code examples for C#. I guess writing programs that use Matlab for calculating is not encouraged by MathWorks, you would became competition that way. Nonetheless I accomplished why I have required to do so I decided to share this with rest of the world.Important:I was using R2010a version of Matlab. I realize that there is newer version. But I had only this version at my disposal. Since interface for communicating with Matlab server is dependent of installed Matlab version and registry entries it may have been different with yours. But I suspect not to much. I also tries with 7.1 and (if I remember correctly) it required only to swap reference in Visual Studio. But again... it was only test so there might be other problems that I am not aware of.Let's start with simple console application. Lets call it MatlabTest. First we will add dll reference with COM interface. Click RMB on project and choose [Add Reference] option. In new window click COM tab. In search text box write 'Matlab'. Then choose "Matlab Application (Version 7.10) Type Library".You should get new reference like below:

Great. Now we should test if it is working. In order to use it we should create our Matlab server from C# application. To that we can add code to our main program:HideCopy Codevar activationContext = Type.GetTypeFromProgID("matlab.application.single");var matlab = (MLApp.MLApp)Activator.CreateInstance(activationContext);Console.WriteLine(matlab.Execute("1+2"));Console.ReadKey();This code will create single Matlab COM server through Activator class. Program Id "matlab.application.single" means single Matlab COM server for our application. When it will try to create another Matlab, it will just return reference to the same object. Contrary to that we could use "matlab.application" which will create another instance of Matlab any timeActivator.CreateIntancemethod will be executed. In more complex applications or for web applications or other programs which run for long time it may creates big memory leaks since 1 instance cost around 220 Mb (on 64 bit Windows 7 and Matlab R2010a).After creating Matlab program execute simple sum of 2 integers, just for test of communication we don't need anything more sophisticated. It should return also simple string in console:

It's really simple and more important it works!This way we can send and receive string messages with MATLAB only. It's not much useful. Also there is one way to find out if our statement had errors. It will have 'error' string in response.Let's try to run something like this: '1*', which will result in error:

So to check our command had errors we have to check if output string have "??? Error" in it.To send some parameters along with our command we have to use on of 'Put*' methods. Best is one calledPutWorkspaceData. It takesthree parameters. First is desired name of our new Matlab variable. Two other are much more tricky. To set variable correctly (so you could reference it in command) you must use global workspace. But it is called? This one took much more time then I would want. It is not mentioned in documentation of this method. If I remember it right I found it in some code example and it should be only "base". In the end I created in my application another method that encapsulatedPutWorkspaceDataand forget about it. Third parameter is value of our variable. It should be simple. Let's change our code to:HideCopy Codematlab.PutWorkspaceData("a", "base", 2);Console.WriteLine(matlab.Execute("a*a"));Result will as below:

But it is just int. What about more complicated structures? How about multiplication of two vectors? Matlab is using .NET type double to send and receive information with our application. Again I did not find it anywhere in documentation, but rather reverse engineered this from data returned from Matlab.So let us try send 2 arrays of doubles. and multiplicate them in Matlab. First will be named 'a' and second 'b'. Matlab command will be "a'*b". Transposition will give us nice matrix instead for single number.HideCopy Codematlab.PutWorkspaceData("a", "base", new[]{2d,3d,1d});matlab.PutWorkspaceData("b", "base", new[]{4d,3d,2d});Console.WriteLine(matlab.Execute("a'*b"));And in return we will get:

Next step will be to return this output to our console app. To do that we can useGetWorkspaceDatathat works similar toPutWorkspaceDataor... we can useGetVariablemethod. This one returns dynamic so our application needs to run on .NET 4. It takes to parameters name of variable we want to return from Matlab and again name of workspace. You really should save this string as const somewhere. Change our code to:HideCopy Codematlab.PutWorkspaceData("a", "base", new[]{2d,3d,1d});matlab.PutWorkspaceData("b", "base", new[]{4d,3d,2d});Console.WriteLine(matlab.Execute("c=a'*b"));var c = matlab.GetVariable("c", "base");After that in our console app we will have variable c and it will be two dimensional array of doubles. To show values of this array in console we can just iterate it with simpleforeachloop. But instead that we will iterate two of the dimensions. This will give us info about values and dimensions of this matrix.HideCopy Codefor (var i = 0; i < c.GetLength(0); i++){ for (var j = 0; j < c.GetLength(1); j++) Console.Write(c.GetValue(i, j) + " "); Console.WriteLine();}

Ok.That was matrix. How about vectors? Luckily vectors are for Matlab just special case of matrix so it will spit out two dimensional array also. More complex is case of empty matrix. No it is not null. It would be to easy. Instead it is special type Missing. I guess it have some logic behind. Null would indicate that variable have no value at all or this is not defined. But we have empty matrix so this is not defined nor this is lack of value. So why not just array with zero values in it? No idea.Lets try run code like below to test it:HideCopy CodeConsole.WriteLine(matlab.Execute("c=a'*b"));Console.WriteLine(matlab.Execute("d=[]"));var c = matlab.GetVariable("c", "base");var d = matlab.GetVariable("d", "base");for (var i = 0; i < d.GetLength(0); i++){ for (var j = 0; j < d.GetLength(1); j++) Console.Write(d.GetValue(i, j) + " "); Console.WriteLine();}Running those command in Matlab will work just fine. Instead of that error will be throwed on first for loop:

Not very nice. To prevent this errors application have to check if dynamic type returned from matlab is in fact empty (Missing). Not very clean it is better to wrap this in other method that will perform this check for us whenever we want to get our data from Matlab. In my project I ended up writing few methods for returning vectors, matrices, numbers, strings etc. Vector one looked like this:HideCopy Codepublic static Vector GetVector(this MLApp.MLApp matlabComObject, string variabla_name){ var dynamicVariable = matlabComObject.GetBaseWorkSpaceVariable(variabla_name); var dataList = new Vector();

if (TypeChecker.IsVector(dynamicVariable)) { dataList = Vector.DynamicToVector(dynamicVariable); } else if (TypeChecker.IsNumber(dynamicVariable)) { dataList.Add(dynamicVariable); } else if (TypeChecker.IsEmptyMatrix(dynamicVariable)) { //do nothing empty vector or matrix ([0x0] or [1x0]) } else throw new Exception(string.Format( "Type of dynamic variable ({0}) is not supproted!", dynamicVariable.GetType())); return dataList;}TypeChekerchecks for type of dynamic. It's pretty straightforward. For our Missing type it's just one line:HideCopy Codepublic static bool IsEmptyMatrix(object dynamicVariable){ return dynamicVariable.GetType() == typeof(Missing); }After checking type of dynamic we can just cast it to another type to take advantage of static properties of language. Why use dynamic at all? First I think that ref and out method parameters are messy and second: I preferHideCopy Codevar d = matlab.GetVariable("d", "base");fromHideCopy Codeobject e;matlab.GetWorkspaceData("d", "base", out e);It is only 1 line. And since object you have to create first and then cast it also don't bother and just use dynamic. But I guess it is just what will you like better.String are much more friendly and there are just string. Or null.Now we know how to put and get data from Matlab. How to execute commands and check them for errors.If you executed any of these example you probably take notice of very simple Matlab window which have opened during life of your console app. If you terminate it by disabling debugging or it will close due to error, Matlab window will remain opened. If not it will close nicely with console window. But still it huge memory leak risk if no maintained properly. To that I recommend creating some special class that will create instance or instances of Matlab. It should track or of created instances and in case anything bad happens (but dynamic variable cast is probability) it will close all instances prior of application exit. Tracking should be employed throughWeakReferenceclass, so whenever Garbage Collector would want to destroy Matlab instance it should not be stopped by our tracking class. To destroy COM instance we can use methodMarshal.FinalReleaseComObject. So with weak reference code for that will look like this:HideCopy Codepublic static void Release(WeakReference instance){ if (instance.IsAlive) { Marshal.FinalReleaseComObject(instance.Target); }}Method Quit of matlab server instance does not close it immediately and code above will.If you want to hide that popup Matlab window you can set this in it's instance:HideCopy Codematlab.Visible = 0;This way it will fade away and run as service.This most basic info about Matlab in C#, but it will get you started. So happy coding.

There is nice example in theMATLAB Central.It shows three ways on how to communicate withMATLAB:1. COM2. MATLAB .NET Bulider3. MATLAB compilerCOM(I do not have any experience with it)Cons: MATLAB is required to be installed on the target computer.MATLAB .NET buildercompiles your MATLAB code to the .NET assembly and you can use it directly.Pros: MATLAB is not required to be installed on the target computerCons: It's expensiveMATLAB compilercompiles your MATLAB code into a C/C++ library or EXE file. You can use it throughP/Invoke.Pros: MATLAB is not required to be installed on the target computerCons: It's expensive, a lot of P/Invoke.

Yes, this is possible. For details, take a look at: Calling a MATLAB function from C# Integrating MATLAB with C# MATLAB CompilerIf you need a quick and dirty way to wrap MATLAB code with a C# GUI (e.g. WinForms), one option is to create an exe from your MATLAB code (.m) - from .NET, you can then easily start this exe as a new process. Note that this approach may not be the best in some situations, beacuse the delay introduced with an exe call can be quite substantial (as the other answer explains).An example: first, write MATLAB code as a function:function y=SamplePlot(p, d, w, t)numericValueP=str2num(p);numericValueD=str2num(d);numericValueW=str2num(w);time=str2num(t);

%... do stuff ...plot(...);Input parameters will be passed to this code as string parameters via command line, hence they are converted viastr2num. E.g. a MATLAB callSamplePlot('1', '2', '3', '4')will be represented asSamplePlot.exe 1 2 3 4Now, create a standalone console app from .m file: in MATLAB console, write:deploytoolName: SamplePlot.prj (for example). Target: Console application. Add .m file. Package: add MCR (this is MATLAB Compiler Runtime - this is what an end-user will need if he doesn't have MATLAB installed; for local testing, you don't need to add this). Then use:mbuild -setupFinally, click 'build' icon. After some time, an exe is generated. Now, you can start this exe as a process from a C# application, e.g. on button click:private void button1_Click(object sender, EventArgs e){ string p=TextBox1.Text; string d=TextBox2.Text; string w=TextBox3.Text; string t=TextBox4.Text; string params = String.Format("{0} {1} {2} {3}",p,d,w,t); System.Diagnostics.Process.Start("SamplePlot.exe", params);}I left out some minor details, but this is one possible option.(If I recall correctly, an assembly can be generated this way as well; you can then call the assembly instead of an exe file).shareimprove this answereditedSep 10 '13 at 20:15

answeredSep 10 '13 at 19:10

w1281,0472826

1

MATLAB has a product (MATLAB Builder NE) built on top of the MATLAB Compiler specifically to generate .NET assemblies:mathworks.com/products/netbuilder. No need to mess with EXE files, you could use the generated assembly as any other .NET library. The result of course is dependent on theMCRAmroSep 11 '13 at 2:12

add a comment

up vote1down voteI'm pretty unfamiliar with C# but eventually happened to use .NET classes from MATLAB.So, you could also do it the other way round, than the previous answers suggest:Since MATLAB is able to create/open .NET gui-elements like dialog, I guess you should also be able to open your .NET-GUI from MATLAB an then plug in your MATLAB-Code via Callbacks. See e.g.:http://www.mathworks.de/de/help/matlab/matlab_external/getting-started-with-net.htmlDepending on how frequently you want to execute matlab-code from your gui and how long the matlab-processing time usually is, this also avoids the pretty large overhead that's e.g. introduced by using a .exe generated with the MATLAB compiler. Say, you'd like to do quick matrix-calculation operations taking less than a second with every other button-click, than starting a standalone.exe everytime would make your gui pretty useless.