MATLAB is a numerical computing environment for engineering applications. It supports communicating with and controlling hardware and processing and visualizing data from that hardware, which makes it a very popular platform for writing the software that goes with custom hardware solutions. It also supports creating user interfaces too, but they tend to look outdated and clunky. 
For example, the control and display software for your custom pump controller system can easily be written in MATLAB. It would run on a PC that is connected to your hardware, lets the user turn the system on and off, set parameters such as pump cycle delays and display graphs showing overall efficiency or total energy input. You can compile all the MATLAB code and sell it, along with your hardware and the MATLAB compiler runtime, as a product.
But what are your options when you want a sleeker, more modern UI with a ribbon bar, interactive graphs and UI themes or skins? The most economic solution with a relatively short time-to-market, is to create a .NET based UI which connects to your MATLAB functions. In this article, I’ll elaborate on how exactly this works.
The MATLAB programming language is also called ‘m-code’ and is saved in files with an .m extension. You can compile these m-files into a .NET dll using MATLAB builder NE. In the examples below, MATLAB has compiled all m-files into MatlabExample.dll (providing methods in the MatlabExample namespace), and the .NET C# project has a reference to this dll.
First, lets look at an m-file, loading an MyObject file from the local filesystem (or creating a default MyObject if the file does not exist yet):
function [MyObject,Error]=LoadFromFile(Id)
% Create a Structure with the Default Settings
Error=0;
loadpath=strcat(Setting.Path,Id,Setting.MyObjectExtension);
% Check if File exists
if exist(loadpath,'file')==2 %File exists
load(loadpath,'-mat');
else
MyObject=CreateDefaultObject(Id);
Error=202;
end
end
The MyObject file is a file saved by MATLAB, using a binary format as in the example below:
function Create(MyObject) % Creates and saves a MyObject MyObject.Id = '123'; MyObject.Foo = 1.2; MyObject.Bar = 9.99; MyObject.LoremIpssum = 3.14; MyObject.Name = 'sample'; savePath=strcat(Setting.Path,MyObject.Id, Setting.MyObjectExtension); save(savePath,'MyObject','-mat'); end
The following C# uses the m-code and wraps its functionality into a MyObject class :
public class MyObject { private static readonly Dictionary<String, MyObject> _instances = new Dictionary<string, MyObject>(); private MWStructArray _settings; private MatlabExample.MyObject _myObjectFactory = new MatlabExample.MyObject(); private string _id; public enum DoublePropertyType { [StringValue("Foo")] KEY_FOO, [StringValue("Bar")] KEY_BAR, [StringValue("LoremIpssum")] KEY_LOREMIPSUM } public enum StringPropertyType { [StringValue("Name")] NAME } public double this[DoublePropertyType name] { get { return ((MWNumericArray)_settings[StringEnum.GetStringValue(name)]).ToScalarDouble(); } set { _settings[StringEnum.GetStringValue(name)] = value; } public String this[StringPropertyType name] { get { return ((MWCharArray)_settings[StringEnum.GetStringValue(name)]).ToString(); } set { _settings[StringEnum.GetStringValue(name)] = value; } } // Private constructor, calls LoadFromFile private MyObject(string myObjectId) { this._id = myObjectId; var ret = _myObjectFactory.LoadFromFile(2, myObjectId); this._settings = (MWStructArray) ret[0]; int error = ((MWNumericArray) ret[1]).ToScalarInteger(); if (error != 0) throw new ApplicationException("Failed to load MyObject."); } // Retrieves a MyObject with a given id. public static MyObject GetInstance(String myObjectId) { MyObject instance; if (! _instances.TryGetValue(myObjectId, out instance)) { lock(_instances) { if (! _instances.TryGetValue(myObjectId, out instance)) { instance = new MyObject(myObjectId); // call private constructor _instances.Add(myObjectId, instance); } } } return instance; } }
Now you can access properties of the MyObject with ID “123” like this:
MyObject obj = MyObject.GetInstance(“123”); // Identifier "123" is used for the filename (minus extension) by the m-code to load data
Double foo = obj[MyObject.DoublePropertyType.KEY_FOO]; // access a Double property
Matrices can be accessed in C# as follows:
public DataPoint[] GetAverage(int averageIndex) { if (_xAverage == null) return new DataPoint[0]; averageIndex++; // MATLAB index starts at 1 int numberOfSamples = _xAverage.Dimensions[1]; DataPoint[] points = new DataPoint[numberOfSamples]; for (int j = 1; j <= numberOfSamples; j++) { points[j - 1] = new DataPoint((double)_xAverage[averageIndex, j], (double)_yAverage[averageIndex, j]); } return points; }
Once you have wrapped all input and output functions in your m-code for C#, you can build a GUI using any .NET control libraries you want. Here is an example of a DevExpress-based GUI we built at ChasmX:
For completeness’ sake, here are the enum helper classes used in the above code snippets.
public class StringValue: System.Attribute { private string _value; public StringValue(string value) { _value = value; } public string Value { get { return _value; } } } public static class StringEnum { public static string GetStringValue(Enum value) { string output = null; Type type = value.GetType(); FieldInfo fi = type.GetField(value.ToString()); StringValue[] attrs = fi.GetCustomAttributes(typeof (StringValue), false) as StringValue[]; if (attrs.Length > 0) { output = attrs[0].Value; } return output; } public static object Parse(Type type, string stringValue, bool ignoreCase) { object output = null; string enumStringValue = null; if (! type.IsEnum) throw new ArgumentException(String.Format("Type must be an Enum, was {0}", type.ToString())); foreach (FieldInfo fi in type.GetFields()) { StringValue[] attrs = fi.GetCustomAttributes(typeof (StringValue), false) as StringValue[]; if (attrs.Length > 0) enumStringValue = attrs[0].Value; if (string.Compare(enumStringValue, stringValue, ignoreCase) == 0) { output = Enum.Parse(type, fi.Name); break; } } return output; } }

Hello Arne,
Great information, and I was looking for something like that a while ago..
Thanks for sharing,
Sami
p.s.
sorry, but not to be picky,
there is a misspell in the “function CreateMyObject)” I think it should be as follows ” function Create(MyObject)”, where a “(” was missing.
Comment by Sami Oweis — February 4, 2013 @ 12:46 pm
Hey Sami,
I’m glad you found it useful! Thanks for pointing out the syntax error, it should be fixed now.
Arne
Comment by Arne Joris — February 6, 2013 @ 2:52 pm