Click here to Skip to main content
15,886,007 members
Articles / Programming Languages / C#

Using Matlab from C# Application

Rate me:
Please Sign up or sign in to vote.
4.00/5 (1 vote)
21 Nov 2015CPOL7 min read 8.3K   4   2
Using Matlab from C# application

While writing an application for my Masters degree diploma, I wrote a simple application that was using COM Matlab server. I have found it hard to use it mainly due 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 become competition that way Smile. Nonetheless, I accomplished what I was required to do, so I decided to share this with the rest of the world.

Important: I was using R2010a version of Matlab. I realize that there is a newer version. But I had only this version at my disposal. Since the interface for communicating with Matlab server is dependent on installed Matlab version and registry entries, it may have been different from yours. But I suspect not to much. I also tried 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 a simple console application. Let's 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".

Image 2

You should get a new reference like below:

Image 3

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:

C#
var 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 a 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.CreateInstance method will be executed. In more complex applications or for web applications or other programs which run for a long time, it may create big memory leaks since 1 instance costs around 220 Mb (on 64 bit Windows 7 and Matlab R2010a).

After creating Matlab program, execute a simple sum of 2 integers, just for test of communication, we don't need anything more sophisticated. It should return a simple string in console:

Image 4

It's really simple and more important, it works! Smile

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:

Image 6

So to check our command had errors, we have to check if output string has "??? Error" in it.

To send some parameters along with our command, we have to use on of 'Put*' methods. Best is one called PutWorkspaceData. It takes 3 parameters. First is desired name of our new Matlab variable. Two others 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 than I would want. It is not mentioned in the 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 another method in my application that encapsulated PutWorkspaceData and forgot about it Smile. The third parameter is the value of our variable. It should be simple. Let's change our code to:

C#
matlab.PutWorkspaceData("a", "base", 2);
Console.WriteLine(matlab.Execute("a*a"));

Result will be as below:

Image 8

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 the documentation, but rather reverse engineered this from data returned from Matlab. So let us try to send 2 arrays of doubles and multiply them in Matlab. First will be named 'a' and second 'b'. Matlab command will be "a'*b". Transposition will give us a nice matrix instead for single number.

C#
matlab.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:

Image 9

The 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 two parameters, name of variable we want to return from Matlab and again name of workspace. You really should save this string as const somewhereSmile. Change our code to:

C#
matlab.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 a simple foreach loop. But instead of that, we will iterate two of the dimensions. This will give us information about values and dimensions of this matrix.

C#
for (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();
}

Image 11

Ok. That was matrix. How about vectors? Luckily, vectors are for Matlab just a special case of matrix so it will spit out two dimensional array as well. More complex is the case of empty matrix. No, it is not null. It would be to easy. Instead, it is a special type Missing. I guess it have some logic behind. Null would indicate that variable has no value at all or this is not defined. But we have an empty matrix so this is not defined nor is this lack of value. So why not just array with zero values in it? No idea.

Let's try to run code like below to test it:

C#
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 thrown on first for loop:

Image 12

Not very nice. To prevent these errors, the application will have to check if dynamic type returned from matlab is in fact empty (Missing). Not very clean, it is better to wrap this in another 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:

C#
public 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 supported!", dynamicVariable.GetType()));
    return dataList;
}

TypeCheker checks for type of dynamic. It's pretty straightforward. For our Missing type, it's just one line:

C#
public 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 prefer:

C#
var d = matlab.GetVariable("d", "base");

from:

C#
object e;
matlab.GetWorkspaceData("d", "base", out e);

It is only 1 line. And since you have to create object first and then cast it also don't bother and just use dynamic. But I guess it is just what you will like better.

Strings are much more friendly and there are just strings. Or null. Smile

Now, we know how to put and get data from Matlab. How to execute commands and check them for errors.

If you re executed any of this example, you probably will take notice of a very simple Matlab window which will have opened during the 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 a memory leak risk if not 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 Smile), it will close all instances prior to application exit. Tracking should be employed through WeakReference 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 method Marshal.FinalReleaseComObject. So with weak reference code for that will look like this:

C#
public static void Release(WeakReference instance)
{
        if (instance.IsAlive)
        {
            Marshal.FinalReleaseComObject(instance.Target);
        }
}

Method Quit of matlab server instance does not close it immediately and the code above will.

If you want to hide that popup Matlab window, you can set this in its instance:

C#
matlab.Visible = 0;

This way, it will fade away and run as service.

This most basic information about Matlab in C#, but it will get you started. So, happy coding. Smile

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Poland Poland
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Questionregarding class in matlab Pin
Member 1550502018-Jan-22 20:10
Member 1550502018-Jan-22 20:10 
AnswerRe: regarding class in matlab Pin
n.podbielski5-Jul-22 21:35
n.podbielski5-Jul-22 21:35 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.