If someone still looks for this in 2021:
C# Module :
using System;
namespace dotNetLib
{
public class API
{
static public void DoSomething()
{
Console.WriteLine("Hello From C#!");
}
}
}
C++ Mono :
#include <mono/jit/jit.h>
#include <mono/metadata/assembly.h>
#include "module.h" // unsigned char asmData[SIZE] = { 0x4D, 0x5A, 0x90, 0x00, 0x03...
MonoDomain* domain;
MonoAssembly* assembly;
using namespace std;
#define log(fmt,...) printf(fmt "\n",__VA_ARGS__);
#define error(code) {log("exited with error %d",code);getchar();return code;}
int LoadFromFile();
int LoadFromMemory();
#define LOAD_FROM_MEMORY true
int main()
{
if (LOAD_FROM_MEMORY)
{
LoadFromMemory();
}
else
{
LoadFromFile();
}
}
int LoadFromMemory()
{
log("Initializing Domain...");
mono_set_dirs(".\\lib", "");
domain = mono_jit_init_version("myapp", "v4.0.30319");
if (!domain) error(-2);
log("Loading Image...");
MonoImageOpenStatus status;
MonoImage* image = mono_image_open_from_data((char*)asmData, sizeof asmData, false, &status);
if (!image) error(-3);
if (status != MONO_IMAGE_OK) error(-4);
log("Loading Module...");
assembly = mono_assembly_load_from(image, "", &status);
if (!assembly) error(-5);
if (status != MONO_IMAGE_OK) error(-6);
log("Getting Class...");
MonoClass* getClass = mono_class_from_name(image, "dotNetLib", "API");
if (!getClass) error(-7);
log("Getting Method...");
MonoMethod* method = mono_class_get_method_from_name(getClass, "DoSomething", 0);
if (!method) error(-8);
log("Calling Method...");
void* params[1] = { NULL };
MonoObject* returnVal = mono_runtime_invoke(method, NULL, params, NULL);
getchar();
log("Cleaning Up...");
mono_jit_cleanup(domain);
}
int LoadFromFile()
{
log("Initializing Domain...");
mono_set_dirs(".\\lib", "");
domain = mono_jit_init_version("myapp", "v4.0.30319");
if (!domain) error(6);
log("Creating Module...");
assembly = mono_domain_assembly_open(domain, "dotNetLib.dll");
if (!assembly) error(7);
MonoImage* image = mono_assembly_get_image(assembly);
if (!image) error(8);
log("Getting Class...");
MonoClass* getClass = mono_class_from_name(image, "dotNetLib", "API");
if (!getClass) error(9);
log("Getting Method...");
MonoMethod* method = mono_class_get_method_from_name(getClass, "DoSomething", 0);
if (!method) error(10);
log("Calling Method...");
void* params[1] = { NULL };
MonoObject* returnVal = mono_runtime_invoke(method, NULL, params, NULL);
getchar();
log("Cleaning Up...");
mono_jit_cleanup(domain);
}
- If you have dependencies issues, use Fody/Costura
- If you want to load mscorlib.dll from memory
you need to do some changes in mono source code or use a virtual file system like BoxedAppSDK or Turbo.Net or Enigma Virtual Box (free)
To embed and run mscorlib.dll from memory you need to store it as a byte array and use mono_register_bundled_assemblies()
to register them.
C++ Mono :
static MonoBundledAssembly _mscorlib = { "mscorlib.dll", mscorlib, sizeof mscorlib };
int LoadFromMemory()
{
MonoBundledAssembly* bundled[1];
bundled[0] = &_mscorlib;
mono_register_bundled_assemblies((const MonoBundledAssembly**)bundled);
log("Initializing Domain...");
...
That's it!