Well, I finally got a really rough prototype going of some C# code making my sandbox engine create a renderer and attach it to a .NET window. Here’s a screenie…
I’ve been embedding mono into my game engine, and decided that what I needed was a code generator to generate C++ classes which wrap .NET classes that exist inside the sandboxed runtime.
I’ve decided on StringTemplate for the templating side of it, and after trying to write a template without first knowing what the class should actually look like, I set about writing an initial prototype of what I would like my generator to eventually produce. This went quite smoothly (if rather slowly), and eventually I found that my application, whilst calling all the .NET code I wanted it to, was crashing when trying to free some memory.
I eventually found that my problem was that I shouldn’t be calling free for a pointer that was allocated using g_malloc, because that’s just asking for trouble. However, g_free, just won’t compile (well, link actually), not in a million years, not in my code (but for some reason it does in libmono). However, the lovely people over at the mono-devel mailing list said I should use mono-free (which wasn’t in my library definition, causing me much angst). Eventually I edited mono.def, recompiled mono, and my code, and what do you know? It works.
Next stop, a code generator.
So today I spent some time building embedded Mono into my game engine (if you can call it that, it’s pretty skeletal so far). It’s pretty poorly done at the moment (design-wise), but I can execute code from a .NET dll within my application. What I didn’t realise until just now, was that the mono runtime will happily load dll’s built with Microsoft’s compiler, which means I don’t even have to worry about needing a separate build environment for the C# code (although it’s pretty easy, just run xbuild on your project/solution from cygwin).
The next steps here will probably be along the lines of turning the runtime stuff into some sort of script host, and coming up with patterns for writing/generating bindings between the two environments. I think I’ll investigate SWIG for this. Binding C# code to C++ types will be fairly easy – the C++ type just needs to register all of its member functions with the runtime, and then a wrapper around these can be written in C# in much the same way as you would wrap any other C dll, using the extern keyword and the MethodImplAttribute. On the other hand, accessing C# types from within C++ requires a fair amount of code (somewhat like using reflection in C#), and so it will be necessary to use some sort of code generator to generate efficient wrappers.
I have been trying (I use this term loosely, since I’ve probably only spent a slightly long working day on it), for a couple of weeks now to write a C++ application which spins up an embedded Mono runtime environment, and executes some C# code – my aim being to write a game engine which uses C# as its scripting language.
All of this would have been quite simple had I not decided that I want my engine to be 64-bit from the get-go, and so started my long journey to getting mono-embedded working.
First, I was under the impression (which turned out to be right), that I would need to build all of mono from source, so I checked out the source code (which took a long time my mono folder is 1.72GB on disk, although some of that must be binaries surely?), only to find that only the runtime can be built from Visual Studio (the framework and compilers must be built from cygwin – autotools, YUCK!). So I then asked the community how much I needed to build, and was told I only needed a 64-bit runtime. So, I tried to build the runtime in Visual Studio 2010, but couldn’t, so I moved to Visual Studio 2008, where I eventually managed to get the runtime compiling, but found there was a bug in the code which I later fixed on the advice of one of the community members.
So finally, I had a working runtime, only to find that the installed version of the framework I had was too old (it seems the source code I downloaded is much newer than the released 2.6.4 version of mono). So, I had to bite the bullet and install cygwin (which took me a couple of attempts to get right). Anyhow, nearly two hours later and the code is built, installed, and the test embedding application works like a charm.
Thanks especially to shana for this article on building mono for windows. If you’re going to follow it, I recommend installing the cygwin version of make, rather than 3.80 (the article is a little old, and cygwin have fixed their make).
Anyhow, it is way past my bed-time on a Sunday, but I’ll post more about my experiences embedding mono in the future.