Toxocious / Aetherim

A C++ library for accessing Unity's IL2CPP classes, methods, and fields during run-time.
GNU General Public License v3.0
65 stars 16 forks source link

Add wrapper for creating and loading custom domain logic #11

Open Toxocious opened 1 year ago

Toxocious commented 1 year ago

It should be possible to allow the creation and loading of custom domains from custom .cs files.

I don't know if this would be useful, but it's likely possible and it extends the usability of Aetherim, so it's worth checking out.

I could also be overthinking this when there's much simpler ways of going about custom C# script execution.

The implementation details for this is rough and incomplete, and comments regarding the issue as a whole would be gratefully appreciated.

Implementation Details

We would use IL2CPP's il2cpp_init() and il2cpp_domain_set() export to initialize a new domain.

Aetherim doesn't currently expose these for use, but can be added pretty easily. A rough example can be seen here, though may not be 100% correct.

// api definitions
DEF_API( il2cpp_init, int *, (const char * domain_name) );
DEF_API( il2cpp_init_utf16, int *, (const Il2CppChar * domain_name) );
DEF_API( il2cpp_set_domain, void, (void * domain, bool _) );

// address definitions
DEF_ADDR( il2cpp_init, "il2cpp_init", GameAssemblyHandle );
DEF_ADDR( il2cpp_init_utf16, "il2cpp_init_utf16", GameAssemblyHandle );
DEF_ADDR( il2cpp_set_domain, "il2cpp_domain_set", GameAssemblyHandle );

You'd create a new instance of the domain, and when using it, you'd access it as such:

// get ref to the current domain before we create a new one
const original_domain = Il2cpp::get_domain();

// initialize our custom domain
const domain = Il2cpp:init("Aetherim/CustomDomain");
if ( domain != original_domain )
{
    // mono_thread_push_appdomain_ref / is there an il2cpp equivalent?
    mono_thread_push_appdomain_ref(domain);

    const auto custom_domain = Il2cpp::set_domain(domain, false);
    if ( custom_domain ) {
        // attach the thread to the new domain
        Il2cpp::thread_attach( domain );

        // perform w/e custom domain logic here
        // ...

        // reattach to the main thread
        Il2cpp::set_domain(original_domain, true);
    }
}