Expression

How To Call Functions In a MATLAB Generated .NET DLL From C#

Posted on Updated on

This Tutorial does not represent a practical use of  a MATLAB generated .NET DLL since it requires the installation and use of MATLAB and the MATLAB Compiler Runtime (MCR) for a scenario that could be easily handled by a more elegant algorithm such as the one discussed in my earlier post on RPN expression parsing. However, it does seek to demonstrate the principles behind developing an algorithm in MATLAB which could be then exported to a .NET component and reused in any managed language. MATLAB provides a fast prototyping environment which gives the programmer a vast array of tools which she can then use to design and test her algorithms. A subset of these functionalities are provided in the MCR which is basically an installable, free, headless version of MATLAB. Since the MCR is a MATLAB instance it requires the same amount of time for initial loading into memory and will also be as memory intensive as its GUI cousin.

That said,  MATLAB allows the packaging of its code into an encrypted Dll file which can then be executed by the MCR. In addition to .NET, MATLAB code can also be exported to C libraries , Java libraries or an executable file.

The first thing we will do is fire up MATLAB, we will access its computational engine through the use of  of  the eval  function which will return the result of a mathematical expression passed to it as a string.  There are the steps.

  1. Launch MATLAB
  2. Type edit in the MATLAB command window then press enter/return. 
    edit
  3. In the new window create the function as seen below then hit the save button.
    function result = calculator(input)
    result = eval(input);
    end
    
  4. Click File->New->Deployment Project then type calculator in the name box.
  5. Select a location to save the project and .NET Assembly from the type drop down box.
  6. In the .NET Assembly window, under the build tab change the default name of the class to “demo” then drag and drop the calculator.m file unto the class to add it as a method of the class, then hit the compile button. This should create the calculator.dll which can be referenced from your c# application.
  7. Fire up Visual Studio and create a new C# Windows Forms Application, to this application add a reference to the calculator.dll file, you will also need to add a reference to the MWArray.Dll which is located at “C:\Program Files\MATLAB\MATLAB Compiler Runtime\v716\toolbox\dotnetbuilder\bin\win64\v2.0\MWArray.dll” (version dependent path) in order to facilitate the conversion of .NET types to MATLAB types.
  8. GUI for expression parser application.
  9. C# Application code.
    using System;
    using System.Windows.Forms;
    using MathWorks.MATLAB.NET.Arrays;
    using calculator;
    
    namespace DemoCalculator
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                var calc= new demo();            
                MessageBox.Show(calc.calculator((MWCharArray)textBox1.Text)[1].ToString());
            }
            
        }
    }
    
  10. Run the application then enter a mathematical expression and hit the Calculate button, this will send the string to be interpreted by the MCR and return a result to the user, the end.

Reverse Polish Expression Parser in C#

Posted on Updated on

There comes a time in every programmers life when she needs a parser. More so if that programmer works for an accounting company. Its not enough to just do the obvious and use the Java Script expression evaluator, or some other third party library for that matter. After all you can do it yourself, with all the custom trimmings that you require for your current project. The key concept in any mathematical parser is the way it interprets the tokens given to it. In this post I will be using reverse polish notation to represent the expression; which will be evaluated and the answer returned. The code is pretty self explanatory so I will not go into details about how it works, remember this is just my first attempt at this so any recommendations or suggestions will be welcomed. I have also intentionally left out some features in the hopes that this will spur suggestions and recommendations.

Snippets

public struct Token{
        public int _class;
        public string repr;
    }

 

private bool RPN(string expression){
            Regex reg = new Regex(@"\[\b[A-Za-z]+\b(?![\d])\]|[\+\-/\*]|[\d]+(\.[\d]+)?|[()]");
            Stack op_stack = new Stack();

            foreach(Match token in reg.Matches(expression)){
                Token tok = new Token();
                string value = token.Captures[0].Value;

                if(IsNumeric(value)){
                    tok._class = (int)type.num;
                    tok.repr = value;
                    calc_list.Add(tok);

                }else if(IsOperator(value)){
                    while(op_stack.Count != 0 && op_stack.Peek().repr != "("){
                        if (HasPrecidenceOrEqual(op_stack.Peek().repr, value)){
                            calc_list.Add(op_stack.Pop());
                        }
                        else break;
                    }
                    tok._class = (int)type.op;
                    tok.repr = value;

                    op_stack.Push(tok);
                }else if (IsVariable(value)){
                    tok._class = (int)type.var;
                    tok.repr = value;
                    calc_list.Add(tok);

                }else if(value == "("){
                    tok._class = (int)type.var;
                    tok.repr = value;

                    op_stack.Push(tok);
                }else if(value == ")"){
                   while(op_stack.Count != 0 && op_stack.Peek().repr != "("){
                       calc_list.Add(op_stack.Pop());
                    }
                   if (op_stack.Count != 0) op_stack.Pop();
                }
            }
            while(op_stack.Count != 0){
                calc_list.Add(op_stack.Pop());
            }

            return true;
        }

Full source code listing at github