Pass callback argument from C# to unmanaged C++
Asked Answered
S

2

5

I have some of unmanaged C++ dynamic library and C# GUI application, using it. I want to pass callback via parameters in some library provided methods. Is it possible to pass a callback to unmanaged C++ method from C#.

// unmanaged C++
typedef uint8_t (__stdcall *SomeCallback)();

MYDLL_API uint8_t someMethod(SomeCallback cb);

I'm trying to use library in this way:

// C# part
public delegate Byte SomeDelegate();

[DllImport("mylibraryname.dll")]
public static extern Byte someMethod(ref SomeDelegate pDelegate);

// actuak callback
Byte myCallback() {
    // some code
}

...

// call unmanaged passing callback
static void Main(string[] args) {          
    someMethod(myCallback);
}

I receive error on compilation:

 cannot convert from 'method group' to 'ref SomeDelegate

Am I totally wrong with my approach?

Salish answered 16/7, 2014 at 8:17 Comment(1)
Why is the callback ref in your extern method?Xerosere
G
7

It is because you MUST put the ref modifier before the argument and that forces the it to be a variable. so:

change you extern to:

public static extern Byte someMethod([MarshalAs(UnmanagedType.FunctionPtr)] 
                            ref SomeDelegate pDelegate);

and your call to:

        SomeDelegate action = new SomeDelegate(myCallback);
        someMethod(ref action);

UPDATE: And if you want to pass an argument to the callback (say an int):

public delegate Byte SomeDelegate([MarshalAs(UnmanagedType.I4)] int value);

[DllImport("mylibraryname.dll")]
public static extern Byte someMethod([MarshalAs(UnmanagedType.FunctionPtr)]
                                       ref SomeDelegate pDelegate);

Byte MyMethod([MarshalAs(UnmanagedType.I4)] int value)
{
    return (byte) (value & 0xFF);
}

and calling:

SomeDelegate action = new SomeDelegate(MyMethod);
someMethod(ref action);
Goodrich answered 16/7, 2014 at 8:23 Comment(2)
And what if callback has parameters? Are there some traits?Salish
It will work fine. Just define your delegate to match that and put attributes on the parameters to specify the unmanaged type. Do you want me to update the code?Goodrich
C
0

Update to C# code for .NET 4.8:

public delegate Byte SomeDelegate(int value);

[DllImport("mylibraryname.dll")]
public static extern Byte someMethod(IntPtr pDelegate);

Byte MyMethod([MarshalAs(int value)
{
    return (byte) (value & 0xFF);
}

calling:

SomeDelegate myCallback = new SomeDelegate(MyMethod);

someMethod(Marshal.GetFunctionPointerForDelegate(myCallback));
Cardoza answered 28/6, 2022 at 4:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.