Loren on the Art of MATLAB

July 28th, 2011

Using MATLAB Structures in C# with Builder NE

Guest blogger Peter Webb returns with another in an occasional series of postings about application deployment.

Contents

Structures Simplify Your Interfaces

To demonstrate how to use structures in an C# application deployed with Builder NE, I've written a MATLAB function to compute the time it takes a planet to orbit around the sun. computeOrbit needs three pieces of information about a planet: the planet's name, its mass, and its distance from the sun. It returns the planet's name and the orbital period. By grouping the input and output data into structures, I can give computeOrbit a very simple interface:

function orbit = computeOrbit(planet)

To compute the length of the Martian year, pass in this MATLAB structure:

planet.name = 'Mars';
planet.mass = 6.4185e+023;
planet.smAxis = 2.2792e+011

computeOrbit returns a structure with two fields:

name: 'Mars'
period: 686.88

And because it's a MATLAB function, if you give computeOrbit a vector of planets, it returns a vector of orbits. I'd like my C# interface to computeOrbit to take and return the same kind of structures. For example, if you create a structure array planets with data for the four inner planets, computeOrbit will return a structure array:

 >> [planets(1:4).name] = deal('Mercury', 'Venus', 'Earth', 'Mars');
 >> [planets.mass] = deal(3.3020e+023, 4.8685e+024, 5.9736e+024, ...
                          6.4185e+023);
 >> [planets.smAxis] = deal(5.7910e+010, 1.0821e+011, 1.4960e+011, ...
                           2.2792e+011);
 >> orbits = computeOrbit(planets);
 >> orbits(3)
 ans =
    name: 'Earth'
  period: 365.2641

Declaring MATLAB-Compatible Structures in C#

The C# interface needs two structures: Planet and Orbit. To prevent conflict with similarly named types in other components, I've placed these types in a C# namespace, Uranometria (derived from Greek, it means "measuring the sky"). For convenience, I also provided the C# Planet structure with a constructor, but this is not strictly necessary.

namespace Uranometria
{
  public struct Planet
  {
      public string name;
      public double mass;
      public double smAxis;
      public Planet(string n, double m, double sma)
        { name = n; mass = m; smAxis = sma; }
  }
  public struct Orbit
  {
      public string name;
      public double period;
  }
}

Builder NE will only automatically marshall structure data between identical structures: the C# and MATLAB field names must be exactly the same and the corresponding field data types must be compatible. Here, compatible means conversion from one type to the other occurs without loss of information. Compatibility is an ordered relationship: conversion from integer to double preserves information, but conversion from double to integer might not. C#'s System.Int32 is therefore compatible with MATLAB's double, but not vice-versa.

Use the Orbit and Planet types to define the C# signature of the C# interface function computeOrbit:

public interface IOrbit
{
   Uranometria.Orbit[] computeOrbit(Uranometria.Planet[] p);
}

Since the MATLAB function computeOrbit takes and returns structure arrays, the C# computeOrbit interface function specifies arrays of structures for both the input and output parameters.

Passing Structures between MATLAB and C#

In C#, declare an array of Planet structures:

Uranometria.Planet[] planet = new Uranometria.Planet[4];

I've qualified the type Planet with its namespace because I think it makes the type name clearer. But you could remove the qualification with a using directive.

Next, add some data (here, the data for Mercury) to the the array, using the convenience constructor:

planet[0] = new Uranometria.Planet("Mercury", 3.3020e+023,
                                   5.7910e+010);

Create an instance of the OrbitalMechanics component. This initializes the compenent and starts the MCR.

IOrbit o = new Uranometria.OrbitalMechanicsIOrbit();

Call the computeOrbit MATLAB function, passing it the array of planets:

Uranometria.Orbit[] orbit = o.computeOrbit(planet);

computeOrbit returns an array of Orbit data. Iterate over the array, printing the name and period of each planetary orbit.

foreach (var p in orbit)
  System.Console.WriteLine("{0,-7}  {1,6:f} days", p.name, p.period);

Building and Running the Example

First, download the example code from MATLAB Central. The download consists of the computeOrbit MATLAB function and a Visual Studio project that builds an application which calls computeOrbit. To build the example, you'll need to:

  • Build the IOrbit interface DLL in Visual Studio
  • Create a deploytool project that builds computeOrbit into a .NET assembly.
  • Build the C# application that calls computeOrbit through the IOrbit interface.
  • The file ReadmeStructures.txt contains detailed instructions.

    The downloaded files compile into Orrery.exe, which computes the orbital period of the four inner planets. Run from the DOS command line (make sure you've got your runtime environment set up correctly), it produces a four-row table:

    Planet   Period
    ---------------
    Mercury   87.97 days
    Venus    224.70 days
    Earth    365.26 days
    Mars     686.88 days

    To compute the orbits of other planets, add more data to the array of Planet structures in Orrery.cs and rebuild the C# main application. There's no need to recompile the computeOrbit function.

    How Does Your Code Use Structures?

    Let me know about how your C# programs use MATLAB structures. Is this how you'd expect to pass structures between C# and MATLAB programs? Let me know here.


    Get the MATLAB code

    Published with MATLAB® 7.12

    7 Responses to “Using MATLAB Structures in C# with Builder NE”

    1. Oyster Engiineer replied on :

      The part of this column that I liked best was the clear illustration of how the deal function passes multiple inputs to multiple outputs. Unfortunately, I don’t think that was the primary purpose of the column.

      I got lost pretty quick after that until I did some extra research & discovered that C# is related to .NET & COM some how.

      Apparently you are showing how to do the right interface via C# code to allow the use of MatLab data structures within a .NET or COM application that is built out of MatLab code. Certainly, I see the advantages of MatLab data structures in general so if someone needed to deploy via .NET or COM, this would be important.

      I don’t understand is how this method of deployment is more useful than deploying the MatLab code as a stand alone application. And I’ve browsed thru the documentation trying to find an answer to this question. But, I haven’t found it yet.

      Maybe this capability is an example of what I’ve seen elsewhere within MatLab: A capability is provided without any discussion of why the capability is useful. Anonymous functions in MatLab are a perfect example of this. I understand how to use them & know that some optimization function require them. But, as I’ve discussed with Loren many times, I don’t understand why someone would want to use them.

      Maybe you could expand this example in a future column to illustrate why this is deployment option is attractive compared to the other deployment options.

    2. Andrey replied on :

      Hi Loren,
      Is it possible to compile Matlab classes into .NET assembly?

    3. Peter Webb replied on :

      Oyster,

      You’re right that the primary point of the column was not to explain the deal function. But I’m glad you found that example enlightening. :-)

      You use the capability described in this post when you’re working with multiple shared libraries. If you have a large application, to which many developers contribute, you can make it much easier to manage by partitioning it into independent libraries.

      In that case, you need to create MATLAB data structures in the host program. And once you’ve created them in the host, you need to pass them in to your MATLAB code. This article demonstrates a new feature of Builder NE that makes it easy to pass MATLAB structures from C# to MATLAB and back.

    4. Peter Webb replied on :

      Audrey,

      The MATLAB Compiler (and all the Builder products) can certainly compile MATLAB functions that use MATLAB classes. That is, you can include code that uses MATLAB classes in your compiled applications and shared libraries.

      However, you cannot return an instance of a MATLAB class from a compiled shared library to a host program. Nor can you create an instance of a MATLAB class in a host program and then pass the instance in to your MATLAB code. We’re aware of this limitation, it irks us, and we’re working on a solution.

      But for now, class instances must remain on the MATLAB/MCR side of a compiled application — they can’t be used in native C#, C++ or Java code.

    5. jiro replied on :

      @Oyster Engineer,

      I don’t see deploying as libraries (such as in C#) better (or worse) than deploying as a standalone application. In my view, the situation decides which way to go. As the name suggests, “standalone application” is useful if the part is to be used pretty much as a whole, but if it’s going to be a part of a bigger thing, then I would look at creating components, like libraries and packages.

      I like analogies and forgive me if this one doesn’t resonate, but let’s say that you’re doing some electrical wiring work in the walls of your house and need to wire some cables over from one part of the room to another. One way is to buy a bunch of off-the-shelf, “standalone” extension cables and connect the together to the other location. But a better way is to buy a roll of plain electrical wires, stretch them through the walls, and attach an outlet at the other end. The roll of wires isn’t meant to be used by itself, but it’s a component that becomes a part of a bigger system.

      While the benefits may not be immediately obvious to pure MATLAB users (like myself and perhaps you), I would think a .NET developer, whose job is to create a large application that has various moving parts, can read the following paragraph from the product page for MATLAB Builder NE and immediately see the value.

      MATLAB Builder™ NE lets you create .NET and COM components from MATLAB® programs that include MATLAB math and graphics, and GUIs developed with MATLAB. You can integrate these components into larger .NET, COM, and Web applications and deploy them royalty-free to computers that do not have MATLAB installed.

    6. Hoi Wong replied on :

      I’m quite new to C# program and I got quite confused after seeing this line:

      IOrbit o = new Uranometria.OrbitalMechanicsIOrbit();
      

      as I didn’t see any structs, class, namespace or interface that’s named OrbitalMechanics in the package.

      Is OrbitalMechanicsIOrbit() a made up function name or it’s some sort of naming requirement to call the compiled MATLAB code? I hope somebody can enlighten me on that.

      I’m also looking to have Labview call MATLAB function somehow and Labview’s CIN looks like a nightmare to me (Seems like I have to write a wrapper every time the Labview developer change the function prototype) to use compiled MATLAB dll. Would .NET be a viable option?

    7. Peter Webb replied on :

      Hoi,

      You’re correct in assuming that OrbitalMechanicsIOrbit is a constructed name — it is formed by concatenating the name of the interface (IOrbit) to the class name (OrbitalMechanics) specified when generating the .NET component. (The readme file included in the download explains this in more detail.)

      As for your other question, I have to confess I don’t know much about Labview, but if it can call .NET, then I suspect Builder NE would be able to create components that Labview can call. (But do please remember I haven’t tested this.)


    MathWorks
    Loren Shure works on design of the MATLAB language at MathWorks. She writes here about once a week on MATLAB programming and related topics.

    These postings are the author's and don't necessarily represent the opinions of The MathWorks.