C#9 introduced unmanaged function pointers (e.g. delegate* unmanaged[Cdecl]<void>). I have been experimenting with these to learn how they work. After upgrading to .NET 5.0.201, I got a new warning:
error CS8909: Comparison of function pointers might yield an unexpected result, since pointers to the same function may be distinct.
According to this issue, taking the reference of a managed function more than once may not always yield the same pointer.
Here is an example of the kind of code that might trigger this warning:
// saves a function pointer in unmanaged code
[DllImport("mylib", CallingConvention = CallingConvention.Cdecl)]
static extern void set_func(delegate* unmanaged[Cdecl]<void> func);
// retrieves the function pointer that was saved above
[DllImport("mylib", CallingConvention = CallingConvention.Cdecl)]
static extern delegate* unmanaged[Cdecl]<void> get_func();
// unmanaged function implemented in C#
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })]
static void MyFunc() {
...
}
void Test() {
// pass our unmanaged callers only function to unmanaged code
set_func(&MyFunc);
...
// sometime later we want to check if unmanaged code still has the same function
// pointer or if it changed
if (get_func() == (delegate* unmanaged[Cdecl]<void>)&MyFunc) { // this line triggers CS8909 warning
...
}
}
I can see how the code would fail to work correctly if the first call to &MyFunc yielded a different function pointer than the second call to &MyFunc. So the warning makes sense.
What alternative could be used to perform the same sort of test that does not lead to the problem indicated by the CS8909 warning?
For example, is this safe?
// identical code from above is omitted for brevity, only Test() method is changed
static readonly delegate* unmanaged[Cdecl]<void> myFunc = &MyFunc;
void Test() {
// pass our unmanaged callers only function to unmanaged code
set_func(myFunc);
...
// sometime later we want to check if unmanaged code still has the same function
// pointer or if it changed
#pragma warning disable CS8909
if (get_func() == myFunc) { // would still trigger warning CS8909 if it was enabled
#pragma warning restore CS8909
...
}
Is there another alternative that could avoid having to disable the warning?