Interfacing C# and MATLAB Using Events

I recently had a situation come up for project where I needed to simulate data flow at a consistent rate into MATLAB so that I can packet it and condition and filter it. The simplest solution I could think of was to run my code in parallel in order to simulate parallel data flow and processing. The problem is however is that MATLAB doesn’t support multi-threading, not directly without having to use another language’s feature (Java, C#, C/C++, Python). Java seemed to be my first choice since for it’s ease of use with MATLAB but it turns out that it doesn’t support event-call backs in MATLAB (not natively anyways). Continuously polling for data isn’t exactly a very elegant solution either. After a bit of researching and experimentation it turns out that MATLAB does support native C# events and delegates providing that it’s constructed according to standard regulations!

In a quick dirty-hack test I mocked up a C# DLL project with the following as the source content:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace DataGenerator
{
    public delegate void DataIsReady(object sender, EventArgs e);
    public class DataGeneratorLogic
    {
        private Thread m_thread;
        private bool m_isRunning;
        private int m_Counter;

        public event DataIsReady Handler;

        protected virtual void OnDataReady(EventArgs e)
        {
            if (Handler != null)
            {
                Handler(this, e);
            }

            Console.WriteLine("Data is Ready!");
        }

        public void Initialise()
        {
            m_thread = new Thread(GenerateData);
            m_isRunning = false;
            m_Counter = 0;
        }

        public void Start()
        {
            Initialise();
            Console.WriteLine("Starting data generation...");
            m_isRunning = true;
            if (!m_thread.IsAlive)
            {
                m_thread.Start();
            }
            else
            {
                Console.WriteLine("Thread has already been started");
            }
        }

        public void Stop()
        {
            Console.WriteLine("Stopping data generation...");
            m_isRunning = false;
        }

        public void GenerateData()
        {
            while (m_isRunning == true)
            {
                Thread.Sleep(1000);
                Console.Write(".");
                m_Counter++;

                if (m_Counter == 10)
                {
                    OnDataReady(EventArgs.Empty);
                    m_Counter = 0;
                }
            }
        }

        public float GetCounter()
        {
            return m_Counter;
        }
    }
}

I compiled it and placed the DLL into a folder in my C drive. In MATLAB I created the class with the following code to call the DLL and assign a listener to the event as the following:

classdef NETEvent < handle
    properties
        data_generator;
    end   
    methods
        function self = NETEvent
            asm=NET.addAssembly('C:\DataGenerator\DataGeneratorLogic.dll');
            self.data_generator = DataGenerator.DataGeneratorLogic();
        end
        
        function r = setListener(self)
           r = addlistener(self.data_generator, 'Handler', @self.dataListener);
        end
        
        function dataListener(self, src,event)
            disp('event fired!');
        end
        
        function run(self)
           self.data_generator.Start(); 
        end
    end    
end

To finish it calling my class code:

obj = NETEvent;
a = obj.setListener;
obj.run();

That’s all there is to it! If you’ve done it right you should be able to see ‘event fired!’ printed out every 10 seconds. You could also call obj.data_generator.GetCounter() to get the current counter value and see it change every second. As long as your “NETEvent class” exists your code will continue running the in background and whenever there’s data ready it’s event callback function will be called. All that’s left now is to feed data into your queue from what ever source files you want and have it collected and processed in MATLAB.

A word of caution:
MATLAB doesn’t allow you to unload DLLs assemblies so if you’re looking to change your code you’re going to have to reboot MATLAB and replace the DLL with your freshly compiled one in order to do so. You could avoid this overhead using Java libraries however but if you’re looking to implement events and listeners like I am it is slightly a bit more difficult. This blog here has a pretty detailed guide of how to do this along with some other neat tricks that’s not documented by Mathworks. I highly recommend checking this out if you’re looking to do a lot of unusual hacking with MATLAB.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s