Fexty12573 / SharpPluginLoader

A C# plugin loader for Monster Hunter World
MIT License
32 stars 2 forks source link

Custom Internal Calls #14

Closed Fexty12573 closed 7 months ago

Fexty12573 commented 7 months ago

Current API (Still up for debate)

Managed API

using SharpPluginLoader.Core;
using SharpPluginLoader.InternalCallGenerator;

[InternalCallManager]
public partial class InternalCalls2 // Name doesn't matter, but partial is required.
{
    [InternalCall]
    public static int Sum(int[] nums); // public static required.

    [InternalCall(InternalCallOptions
        .Unsafe)] // Will suppress the GC transition when invoked. Don't use on long methods.
    public static bool ProcessData(byte[] data, out int result);

    // Non-internal call methods are allowed
    public static int ProcessDatasAndSum(byte[][] datas)
    {
        List<int> results = [];
        foreach (var data in datas)
        {
            if (ProcessData(data, out var result))
            {
                results.Add(result);
            }
        }

        return Sum([..results]);
    }
}

Native API

extern "C" int Sum(int* nums) { ... }

extern "C" bool ProcessData(u8* data, int* result) { ... }

The function name needs to match exactly on the managed and native ends.

Fexty12573 commented 7 months ago

Actually, I will probably change the extern "C" based API to one that requires the native component to only export 2 functions:

struct InternalCall {
    const char* Name;
    void* FuncPtr;
};

// Tells the PluginMananager how many InternalCalls to allocate
extern "C" int get_internal_call_count() { return 2; }

// Retrieves the actual call information
extern "C" void get_internal_calls(InternalCall* icalls) { 
    icalls[0] = { "Sum", &sum };
    icalls[1] = { "ProcessData", &process_data };
}

This also gives you the option to directly bind game functions to internal calls for convenience.