I'm trying to load mono assemblies from memory. My question has two parts, first:
when I use mono_image_open_from_data
and mono_assembly_load_from
combination the assembly dependencies are not loaded. If I load assembly dependencies manually with same methods it seems that they are not added to application domain. So it does not work.
So I want to know if there is any way to load these assemblies from memory.
Second: If it is possible to load assemblies from memory, is it possible to load mscorlib.dll
from memory too? The mono_jit_init tries to load it from library path and if it does not exist in the path mono will fail to initialize. Is there any way to load it from memory?
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);
}
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!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With