Skurdt / SK.Libretro

Libretro wrapper written in C# with support for the Unity game engine
MIT License
28 stars 13 forks source link

Unable to load in IL2CPP build #10

Closed XenuIsWatching closed 2 months ago

XenuIsWatching commented 1 year ago

For IL2CPP, it is unable to marshalling delegates to an instanced methods

System.NotSupportedException: IL2CPP does not support marshaling delegates that point to instance methods to native code. The method we're attempting to marshal is: SK.Libretro.EnvironmentHandler::EnvironmentCallback

which comes from the function in the call stack https://github.com/Skurdt/SK.Libretro/blob/cf14f8392a40119542a9e0d66a89d096ec4aa4db/Scripts/Core.cs#L293

Skurdt commented 1 year ago

In c++, all the needed callbacks have to be global functions, either as static member functions in classes, or a free functions.

You could mark the SetCallbacks() method as static, then modify all the needed functions and members and mark them as static as well. It will basically make the majority of the code static, so only doing this will prevent multiple instances running at the same time. If this even works, supporting multiple instances can probably be done using a list/queue containing data for each instances.

XenuIsWatching commented 1 year ago

yeah... I'm looking into it myself right now. I first just basically just put every instance into a Dictionary when constructed.... but still trying to figure out how to "look up" which instance it is when the core callbacks in to the static function.

I just made it single instanced (static) to keep moving while I think about it, and it's now just whack-a-mole of issues trying to get it to run on Android such as Marshal.GetFunctionPointerForDelegate needs to call static functions as well

Skurdt commented 1 year ago

It should run on Android without using il2cpp though.

I think the only change that was needed was to use persistentdatapath instead of streamingassetspath and load files using unitywebrequest instead of read/write to file.

XenuIsWatching commented 1 year ago

It should run on Android without using il2cpp though.

The ARM64 option gets "grayed out" for Mono, Also only arm64 is supported on Android with OpenXR. Other archs are not supported.

I think the only change that was needed was to use persistentdatapath instead of streamingassetspath and load files using unitywebrequest instead of read/write to file.

yeah, I already did that with using persistentdatapath. I haven't done the unitywebrequest yet..... there is also the issue of where dynamic libraries can be loaded. Due to "security reasons", they can only be loaded from the private app directory which I just retrieved with the function

    private string GetAndroidPrivateAppDataPath()
    {
        string path;
        using (AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
        {
            using (AndroidJavaObject currentActivity = jc.GetStatic<AndroidJavaObject>("currentActivity"))
            {
                path = currentActivity.Call<AndroidJavaObject>("getFilesDir").Call<string>("getCanonicalPath");
            }
        }
        return path;
    }
Skurdt commented 1 year ago

It's probably more a hack than anything but, if running with the included classes, you might be able to use a Dictionary<Thread, XYZ> and look up for the data using Thread.CurrentThread.

I have to say that I'm not in love with the idea of using this in the base/standard implementation. This is really only an issue when using IL2CPP. It might not be necessary once Unity switches from mono to proper .net (I would not wait for that any time soon either...)

XenuIsWatching commented 1 year ago

It's probably more a hack than anything but, if running with the included classes, you might be able to use a Dictionary<Thread, XYZ> and look up for the data using Thread.CurrentThread.

That could work... The only caveat I can come up with is if the libretro core creates its own multithreads and then calls the callback function

gtk2k commented 1 year ago

I'm trying to build Android (Quest), but for now I can get to the point where the so file is copied to the temp folder ($"{GetAndroidPrivateAppDataPath()}/temp"),

Error Unity Exception: Failed to load library 'mame2003_plus_95f911a9-2e26-4038-9928-1aa045e6a6a0' at path '/data/data/com.DefaultCompany.Android_Arcade/files/temp/mame2003_plus_95f911a9-2e26-4038-9928-1aa045e6a6a0.so' ()

Is there any workaround?