Function pointer on generic class delegate

33 views Asked by At

I need to get a FunctionPointerForDelegate to pass a native P/Invoke, but the function resides in a generic class of type myClass

When I try to create the Pointer I get an error of

System.ArgumentException: 'The specified Type must not be a generic type. (Parameter 'delegate')'

Is there any workaround to this?

var c = new MyClass<int>();
c.DoWork();

public class MyClass<T> {

    private protected delegate int MyCompareCallback(int idxA, int idxB);

    private int SortCompareFunction(int idxA, int idxB) {
        return -1; // simplified implementation
    }

    public void DoWork() {
        MyCompareCallback SortCallback = new(SortCompareFunction);
        IntPtr callbackPtr = System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate(SortCallback);
        Console.WriteLine("Success"); // Fails on previous line with System.ArgumentException: 'The specified Type must not be a generic type. (Parameter 'delegate')'
    }

}

1

There are 1 answers

0
Enigmativity On BEST ANSWER

You need to consider that your delegate type MyCompareCallback is actually MyClass<T>.MyCompareCallback. It is a generic type.

When you read the documentation for Marshal.GetFunctionPointerForDelegate it specifically says the System.ArgumentException will be thrown if the delegate is a generic type.

You really have two choices.

(1) remove the generic type parameter from MyClass

public class MyClass
{
    private protected delegate int MyCompareCallback(int idxA, int idxB);
    private int SortCompareFunction(int idxA, int idxB) => -1;
    public void DoWork()
    {
        MyCompareCallback SortCallback = new MyCompareCallback(SortCompareFunction);
        IntPtr callbackPtr = System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate(SortCallback);
        Console.WriteLine("Success");
    }
}

(2) move the delegate outside of MyClass<T>

internal delegate int MyCompareCallback(int idxA, int idxB);
public class MyClass<T>
{
    private int SortCompareFunction(int idxA, int idxB) => -1;
    public void DoWork()
    {
        MyCompareCallback SortCallback = new MyCompareCallback(SortCompareFunction);
        IntPtr callbackPtr = System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate(SortCallback);
        Console.WriteLine("Success");
    }
}