Embedding Mono in a C++ application

On this post we will see how it is possible to embed the Mono runtime in a C++ application.

Why Mono?

Mono can extend the scripting capabilities of your C++ application by providing access to a wide range of languages like C#, F#, Python and Ruby (full list of supported languages). It offers a safe, managed environment with garbage collection, and better performance than most scripting languages.

How to include Mono in your project’s configuration

  1. First of all, download and install Mono from http://www.mono-project.com/download/.
  2. Assuming you installed it at %MONO_ROOT%, add the folder %MONO_ROOT%/include/mono-2.0 to your project’s include folders.
  3. Then, link against the %MONO_ROOT%/lib/mono-2.0.lib library.
  4. Finally, the mono-2.0.dll must be in the DLL search path in order to run your application. This dll is not directly available. In the %MONO_ROOT%/bin folder you will find the libmonoboehm-2.0.dll and libmonosgen-2.0.dll. Copy either (depending on which GC implementation you prefer) on your application’s path and rename it to mono-2.0.dll.

A sample C# class

Now, let’s assume that we have the following C# class, compiled in an assembly called Example.dll. This will be the class that we will interact with from the C++ host application.

Embedding Mono

Initialization

The first thing we need to do, is to initialize the Mono runtime and load our assembly:

Creating C# objects

In order to use the Entity class, we have to construct an instance of it:

The instance is not yet created. The only thing mono_object_new does is to allocate enough memory for one Entity object. In order to instanciate the object, we have to call a constructor.

Invoking constructor and methods

Constructors and methods are invoked in the same way: first obtain a pointer to the MonoMethod representing the constructor or method, prepare any arguments and finally call  mono_runtime_invoke:

The name “.ctor” is a special name that is used to refer to constructor methods.

At this point, an Entity instance is constructed in the Mono runtime. We can now freely some other Entity methods.

We can also retrieve the result of a method on the host application:

Getting/Setting fields

The API also allows us to set/get field values:

Shutting down

When done with Mono we can shut it down in order to release any used resources:

Note that after calling mono_jit_cleanup, you can’t reinitialize the runtime in the same process again. This can be annoying in case you have unit tests running in one process and you are initializing/cleaning up per test (I learned this the hard way). In this case, make sure you initialize and cleanup only once per process.

When running the above code you should see the following output:

Summary

I hope this post can help you in any way. You can find the full source code here.

Check out the Mono documentation for a more detailed info about embedding here.

Leave a Reply

Your email address will not be published. Required fields are marked *