Search code examples
c#c++pinvoke

C++ dll Pinvoke function with function pointer struct in parameter


I'm working on a C# code which uses a C++ dll
One function of the C++ dll takes a struct of 3 function pointers in parameter, I dont know how to manage it any tips or topics ?
I tried this but this doesnt work :

[StructLayout(LayoutKind.Sequential)]
public class DisplayCallBacks
{
    [MarshalAs(UnmanagedType.FunctionPtr)] initProgressBar ();                              
    [MarshalAs(UnmanagedType.FunctionPtr)] logMessage (int msgType, [MarshalAs(UnmanagedType.LPCWStr)] String str);
    [MarshalAs(UnmanagedType.FunctionPtr)] loadBar (int x, int n);                          
}

[DllImport("CubeProgrammer_API.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "setDisplayCallbacks")]
internal static extern void SetDisplayCallbacks(DisplayCallBacks c);

C++ prototypes :

typedef struct displayCallBacks
{
    void (*initProgressBar)();                             
    void (*logMessage)(int msgType,  const wchar_t* str); 
    void (*loadBar)(int x, int n);                        
} displayCallBacks;

void setDisplayCallbacks(displayCallBacks c);

Solution

  • Use IntPtr as the type for the function pointers. Then you can declare a delegate. Here is an example from code I wrote:

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    delegate void PrintLogDelegate(string msg);
    
    PrintLogDelegate pld;
    System.Runtime.InteropServices.GCHandle callbackPrintLog;
    IntPtr ipCBPrintLog = IntPtr.Zero;
    
    pld = new PrintLogDelegate(PrintLogFunc);
    callbackPrintLog = System.Runtime.InteropServices.GCHandle.Alloc(pld);
    ipCBPrintLog = System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate(pld);
    
    
    void PrintLogFunc(string msg)
    {
    
    }
    

    So ipCBPrintLog is what you pass to C++ as a callback.

    Then in your Dispose you have to clean up: callbackPrintLog.Free();