I am trying to call a function in C from my .Net Core application. To dive right in, the C function comes from libmpv render.h and the head of the functions looks like this:
int mpv_render_context_create(mpv_render_context **res, mpv_handle *mpv, mpv_render_param *params);
The problem is I have no clue how to call the function from C#. So I've tried the following:
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern int mpv_render_context_create([Out] out IntPtr renderContext, IntPtr mpvHandle,
        MpvRenderParam[] parameters);
Since the **res parameter should be updated by the function I thought this would make sense. This I tried to call with the following:
var ptr = IntPtr.Zero;
var apiTypePtr = Marshal.StringToHGlobalAuto("opengl");
var i = mpv_render_context_create(out ptr, _mpvHandle, new []
{
    new MpvRenderParam(MpvRenderParamType.ApiType, apiTypePtr),
    new MpvRenderParam(MpvRenderParamType.Invalid, IntPtr.Zero
});
This threw me an AccessViolationException, In fact every time I called the mpv_render_context_create Method I got the same Exception, so when I say "It didn't work" I mean the call threw that exception.
So I then thought maybe I would have to make it a ref parameter:
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern int mpv_render_context_create(ref IntPtr renderContext, IntPtr mpvHandle,
        MpvRenderParam[] parameters);
Which caused the same error when calling it.
I then read in another stackoverflow question, that I should pass the bare IntPtr like the following:
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern int mpv_render_context_create(IntPtr renderContext, IntPtr mpvHandle,
        MpvRenderParam[] parameters);
But first, it didn't work again, and second how would I even get the result from this?
So how should I create and call the function so I can create the render context?
The MpvRenderParam is declared as followed:
[StructLayout(LayoutKind.Sequential)]
public struct MpvRenderParam
{
    public MpvRenderParamType Type { get; }
    public IntPtr Data { get; }
    public MpvRenderParam(MpvRenderParamType type, IntPtr data)
    {
        Type = type;
        Data = data;
    }
}
And The MpvRenderParamType:
public enum MpvRenderParamType
{
    Invalid = 0,
    ApiType = 1,
    InitParams = 2,
    Fbo = 3,
    FlipY = 4,
    Depth = 5,
    IccProfile = 6,
    AmbientLight = 7,
    X11Display = 8,
    WlDisplay = 9,
    AdvancedControl = 10,
    NextFrameInfo = 11,
    BlockForTargetTime = 12,
    SkipRendering = 13,
    DrmDisplay = 14,
    DrmDrawSurfaceSize = 15,
    DrmDisplayV2 = 15
}
Update
I have taken into account all of the resources provided by Mattias Santoro I am just not entirely sure how to translate them into C# as it is a managed language. My Method for calling the mpv function looks like this now:
OpenGlControl.OpenGL.MakeCurrent();
IntPtr ptr;
var apiTypePtr = Marshal.StringToHGlobalAuto("opengl");
var opengl = new MpvOpenGlInitParams {get_proc_address = getProcAdress};
var size = Marshal.SizeOf(opengl);
var arr = new byte[size];
fixed (byte* arrPtr = arr)
{
    Marshal.StructureToPtr(opengl, (IntPtr)arrPtr, true);
    var parameters = new MpvRenderParam[]
    {
        new MpvRenderParam {Type = MpvRenderParamType.ApiType, Data = &apiTypePtr},
        new MpvRenderParam {Type = MpvRenderParamType.OpenGlInitParams, Data = &arrPtr},
        new MpvRenderParam {Type = MpvRenderParamType.Invalid, Data = null}
    };
    var i = mpv_render_context_create(&ptr, _mpvHandle, parameters);
}
The MpvOpenGlInitParams:
[StructLayout(LayoutKind.Sequential)]
public struct MpvOpenGlInitParams
{
    public delegate IntPtr GetProcAdressDelegate(IntPtr ctx, string name);
    public GetProcAdressDelegate get_proc_address;
    public IntPtr get_proc_address_ctx;
    public string extra_exts;
}
Sadly it still throws the same error, I am not sure what I am doing wrong and it's really frustrating.