microsoft / CsWin32

A source generator to add a user-defined set of Win32 P/Invoke methods and supporting types to a C# project.
MIT License
2.09k stars 89 forks source link

MarshalDirectiveException when calling IContextCallback.ContextCallback on .NET 7 #928

Closed roboz0r closed 1 month ago

roboz0r commented 1 year ago

Actual behavior

Attempting to call IContextCallback.ContextCallback with the automatically generated function signature results in the exception:

System.Runtime.InteropServices.MarshalDirectiveException: 'Cannot marshal 'parameter #1': .NET Core does not support marshalling delegates to the _Delegate interface provided by the .NET Framework COM Type Library. To marshal a delegate as an interface, marshal it as an IDispatch pointer.'

Expected behavior

The call completes without error.

Repro steps

  1. NativeMethods.txt content:

    CoGetObjectContext
    IContextCallback
  2. NativeMethods.json content (if present):

    {
    "$schema": "https://aka.ms/CsWin32.schema.json",
    "emitSingleFile": false,
    "public": true,
    "comInterop": {
    "useIntPtrForComOutPointers": true
    }
    }
  3. Any of your own code that should be shared?

I copied the generated interface code and added [MarshalAs(UnmanagedType.FunctionPtr)] to the parameter and it now seems to call successfully.

    [Guid("000001DA-0000-0000-C000-000000000046")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    [SupportedOSPlatform("windows5.0")]
    [GeneratedCode("Microsoft.Windows.CsWin32", "0.2.206-beta+27f494b7ea")]
    public interface IContextCallback
    {
        unsafe void ContextCallback(
          // PFNCONTEXTCALL pfnCallback,
          [MarshalAs(UnmanagedType.FunctionPtr)] PFNCONTEXTCALL pfnCallback,
          ComCallData* pParam,
          Guid* riid,
          int iMethod,
          object pUnk);
    }

Context

AArnott commented 1 year ago

Thanks for the excellent bug report and for sharing the solution you found. I'll research it some and (likely) apply the fix you found to the generated code.

RibShark commented 3 months ago

The same bug seems to apply to IDirectDraw.EnumDisplayModes and the equivalents for the other DirectDraw versions, they need the MarshalAs attribute on the callback param.