Using Matlab From A C#
Using Matlab From A C#
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:
Hide Copy Code
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 time Activator.CreateIntance method 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:
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 takes three 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
encapsulated PutWorkspaceData and forget about it
. Third parameter is value of our
variable. It should be simple. Let's change our code to:
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.
Hide Copy Code
Next step will be to return this output to our console app. To do that we can
use GetWorkspaceData that works similar to PutWorkspaceData or... we can
use GetVariable method. 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:
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
simple foreach loop. But instead that we will iterate two of the dimensions. This will give
us info about values and dimensions of this matrix.
Hide Copy Code
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:
Hide Copy Code
Console.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:
Hide Copy Code
TypeCheker checks for type of dynamic. It's pretty straightforward. For our Missing type
it's just one line:
Hide Copy Code
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 prefer
Hide Copy Code
from
Hide Copy Code
object 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
throughWeakReference class, 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:
Hide Copy Code
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:
Hide Copy Code
matlab.Visible = 0;
3.
MATLAB compiler
If 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 via str2num. E.g. a MATLAB call
SamplePlot('1', '2', '3', '4')
will be represented as
SamplePlot.exe 1 2 3 4
Now, create a standalone console app from .m file: in MATLAB console, write:
deploytool
Name: 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 -setup
Finally, 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 answer
w128
1,0472826
up
vote1do
wn vote
I'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-withnet.html
Depending 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.