I have a question that I can't handle for a week, you won't believe it, I've already checked everything that is possible, but it still doesn't want to work correctly. Now I'm writing a script system for my game engine and I need to dynamically recomile/reload .the dll file that contains my library and scripts. To do this, I do:
- Initialize Mono. (I get an appdomain (MonoDomain*) already created for me)
- Open an assembly file. (dll)
- Get an image from this assembly.
- Use mono (I load internal calls, create C# objects, call functions, etc.).
But at some point I need to recompile/reload this assembly, because I change the script code, well, it's understandable. As I understand from a lot of read documentation and various sources, I do not have to describe the domain, assemblies and images while it is active and for this you first need:
- Create a new domain.
- Upload the image.
- Connect the image to the object assembly (thereby making the image status OK)
- And only then describe the resources from the last domain.
But just so that I don't try, either an error occurs in the mono code, or now I have reached the stage that there are no errors, but here is a pointer to a new image obtained from a newly loaded assembly (with the same name) is the same and thus it turns out that mono continues to use the same image and does not have the updated script values.
This is code of my Mono init:
mono_set_dirs(".", ".");
// 0. Load first domain, init mono + appdomain + load assembly.
const char* domainName = "ForceCS";
const char* assemblyName = "ForceCS.dll";
pMonoDomain = mono_jit_init(domainName);
if (pMonoDomain) {
pMonoAssembly = mono_domain_assembly_open(pMonoDomain, assemblyName);
if (pMonoAssembly) {
pMonoImage = mono_assembly_get_image(pMonoAssembly);
if (pMonoImage) {
AddInternalFunctionsAndScriptClasses(); // mono_add_internal_call ...
}
}
}
Then i do some stuff with my dll like create objects or call methods as i said before. And then try to reload the ForceCS.dll.
// 1. Load new domain (Works fine).
char* newDomainName = "ForceCS";
MonoDomain* newDomain = mono_domain_create_appdomain(newDomainName, NULL);
if (!mono_domain_set(newDomain, false)) {
// Cannot set domain!
}
// 2. Load image. (Works fine)
const char* dllFile = "C:\\Force\\Editor\\ForceCS.dll";
MonoImageOpenStatus status;
MonoImage* newImage = mono_image_open(dllFile, &status); ** Problem here: Shows the same address as before and that means that Mono use same .dll.**
// 3. Load new assembly. (Works fine).
MonoAssembly* assembly = mono_assembly_load_from(newImage, mono_image_get_name(newImage), &status);
if (status != MonoImageOpenStatus::MONO_IMAGE_OK) {
///Cannot load assembly!
}
assembly = mono_assembly_open(dllFile, &status);
newImage = mono_assembly_get_image(assembly);
if (newImage) {
AddInternalFunctionsAndScriptClasses();
}
// 4. Inload old domain.
MonoDomain* domainToUnload = pMonoDomain == nullptr ? mono_domain_get() : pMonoDomain;
if (domainToUnload && domainToUnload != mono_get_root_domain()) {
mono_domain_unload(domainToUnload);
mono_gc_collect(mono_gc_max_generation());
mono_domain_finalize(domainToUnload, 2000);
mono_gc_collect(mono_gc_max_generation());
pMonoDomain = newDomain;
pMonoImage = newImage;
pMonoAssembly = assembly;
}
Final problem that image always stays the same, only it works if i load this assembly with different name like ForceCS1.dll, but its not what i want. Please explain me:
- When i need to close/free domains, assemblies, images.
- What the connection between assembly-image.
- How reload my .dll assembly.
I will be grateful for every answer.