Calling unamanged function which takes a pointer to pointer parameter

Michael Paravicini
Michael Paravicini used Ask the Experts™
on
I am trying to call  a function in C from my .Net Core application. The C function comes from libmpv render.h and the head looks like this:
   
int mpv_render_context_create(mpv_render_context **res, mpv_handle *mpv, mpv_render_param *params);

Open in new window

The problem is, that I have no clue how to call the function from C#.
First of all I have declared the MpvRenderParam struct as follows in C#:
   
[StructLayout(LayoutKind.Sequential)]
public unsafe struct MpvRenderParam
{
    public MpvRenderParamType Type;
    public void* Data;
}

Open in new window


Previously I have defined the Data field to be of type
IntPtr

Open in new window

but in my opinion it makes more sense when it can be an all purpose pointer, so it matches the definition of the C Library.

Following is the MpvRenderParamType enum:

    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
    }

Open in new window


The actual problem


Now I have explained all the data types that were transcribed to C# but the problem still lies in creating the correct definition of the mpv_render_context_create and calling it.
First I tried to define the method like this:
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern int mpv_render_context_create([Out] out IntPtr renderContext, IntPtr mpvHandle,
        MpvRenderParam[] parameters);

Open in new window


And I called it with:
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
});

Open in new window


I also tried changing the first parameter to be a ref or IntPtr but no matter what combination of parameter type and calling it, I always got the same exception:
Exception thrown at 0x0000000055C73D60 (mpv-1.dll) in Otchi.App.exe: 0xC0000005: Access violation reading location 0x0000000000000010.
My last attempt was going into the unsafe part of C# and declaring the method like this:
[DllImport(LibName, CallingConvention = CallingConvention.Cdecl)]
private static extern unsafe int mpv_render_context_create(IntPtr* renderContext, IntPtr mpvHandle,
    MpvRenderParam[] parameters);

Open in new window


And calling it with the following piece of code:
IntPtr ptr;
var test = GCHandle.Alloc("opengl");
var test2 = GCHandle.ToIntPtr(test);
var apiTypePtr = Marshal.StringToHGlobalAuto("opengl");
var i = mpv_render_context_create(&ptr, _mpvHandle, new []
{
    new MpvRenderParam{Type = MpvRenderParamType.ApiType, Data = &apiTypePtr},

    new MpvRenderParam{Type = MpvRenderParamType.Invalid, Data = null}
});

Open in new window


No matter what I tried, I always get the same exception. How can I call the mpv_render_context_create without it throwing an AccessViolationException?
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Eduard GherguArchitect - Coder - Mentor

Commented:
Hi!
Can you have a look at the following sample:
https://github.com/mpv-player/mpv-examples/tree/master/libmpv/csharp

Author

Commented:
Thanks for your reply, however, in the example they use the "wid" approach, where they just embed the video. This is not what i'm looking for, I want to render the video myself into a SharpGL context. I have taken many of the DllImports from the example you have provided, however the method I am having trouble with, is not part of the examples.
Architect - Coder - Mentor
Commented:
Hi,

Try to stick with the original declaration. The first parameter is a double-pointer, IntPtr is actually a void* and the declaration of the function cannot be resolved. Declare also the mpv_render_context, mpv_handle, and mpv_render_param if you haven't done already.

[DllImport(LibName, CallingConvention = CallingConvention.Cdecl)]
private static extern unsafe int mpv_render_context_create(mpv_render_context **res, mpv_handle *mpv,
                              mpv_render_param *params);

Author

Commented:
thank you so much.... Cheers Michael
Eduard GherguArchitect - Coder - Mentor

Commented:
Hi!
My pleasure! Please, let me know if you need more help.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial