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
1.99k stars 84 forks source link

IDxcLibrary.CreateBlobWithEncodingOnHeapCopy is incorrectly generated returning void and not HRESULT #1074

Closed Sergio0694 closed 8 months ago

Sergio0694 commented 8 months ago

Actual behavior

Code for `IDxcLibrary` (click to expand):
```csharp // ------------------------------------------------------------------------------ // // This code was generated by a tool. // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // // ------------------------------------------------------------------------------ #pragma warning disable CS1591,CS1573,CS0465,CS0649,CS8019,CS1570,CS1584,CS1658,CS0436,CS8981 using global::System; using global::System.Diagnostics; using global::System.Diagnostics.CodeAnalysis; using global::System.Runtime.CompilerServices; using global::System.Runtime.InteropServices; using winmdroot = global::Windows.Win32; namespace Windows.Win32 { namespace Graphics.Direct3D.Dxc { [Guid("E5204DC7-D18C-4C3C-BDFB-851673980FE7")] [global::System.CodeDom.Compiler.GeneratedCode("Microsoft.Windows.CsWin32", "0.3.49-beta+91f5c15987")] internal unsafe partial struct IDxcLibrary { /// internal unsafe winmdroot.Foundation.HRESULT QueryInterface(in global::System.Guid riid, out void* ppvObject) { fixed (void** ppvObjectLocal = &ppvObject) { fixed (global::System.Guid* riidLocal = &riid) { winmdroot.Foundation.HRESULT __result = this.QueryInterface(riidLocal, ppvObjectLocal); return __result; } } } public unsafe winmdroot.Foundation.HRESULT QueryInterface(global::System.Guid* riid, void** ppvObject) { return ((delegate *unmanaged [Stdcall])lpVtbl[0])((IDxcLibrary*)Unsafe.AsPointer(ref this), riid, ppvObject); } public uint AddRef() { return ((delegate *unmanaged [Stdcall])lpVtbl[1])((IDxcLibrary*)Unsafe.AsPointer(ref this)); } public uint Release() { return ((delegate *unmanaged [Stdcall])lpVtbl[2])((IDxcLibrary*)Unsafe.AsPointer(ref this)); } public unsafe void SetMalloc([Optional] winmdroot.System.Com.IMalloc* pMalloc) { ((delegate *unmanaged [Stdcall])lpVtbl[3])((IDxcLibrary*)Unsafe.AsPointer(ref this), pMalloc).ThrowOnFailure(); } public unsafe void CreateBlobFromBlob(winmdroot.Graphics.Direct3D.Dxc.IDxcBlob* pBlob, uint offset, uint length, winmdroot.Graphics.Direct3D.Dxc.IDxcBlob** ppResult) { ((delegate *unmanaged [Stdcall])lpVtbl[4])((IDxcLibrary*)Unsafe.AsPointer(ref this), pBlob, offset, length, ppResult).ThrowOnFailure(); } /// internal unsafe void CreateBlobFromFile(string pFileName, winmdroot.Graphics.Direct3D.Dxc.DXC_CP? codePage, winmdroot.Graphics.Direct3D.Dxc.IDxcBlobEncoding** pBlobEncoding) { fixed (char* pFileNameLocal = pFileName) { winmdroot.Graphics.Direct3D.Dxc.DXC_CP codePageLocal = codePage ?? default(winmdroot.Graphics.Direct3D.Dxc.DXC_CP); this.CreateBlobFromFile(pFileNameLocal, codePage.HasValue ? &codePageLocal : null, pBlobEncoding); } } public unsafe void CreateBlobFromFile(winmdroot.Foundation.PCWSTR pFileName, [Optional] winmdroot.Graphics.Direct3D.Dxc.DXC_CP* codePage, winmdroot.Graphics.Direct3D.Dxc.IDxcBlobEncoding** pBlobEncoding) { ((delegate *unmanaged [Stdcall])lpVtbl[5])((IDxcLibrary*)Unsafe.AsPointer(ref this), pFileName, codePage, pBlobEncoding).ThrowOnFailure(); } public unsafe void CreateBlobWithEncodingFromPinned(void* pText, uint size, winmdroot.Graphics.Direct3D.Dxc.DXC_CP codePage, winmdroot.Graphics.Direct3D.Dxc.IDxcBlobEncoding** pBlobEncoding) { ((delegate *unmanaged [Stdcall])lpVtbl[6])((IDxcLibrary*)Unsafe.AsPointer(ref this), pText, size, codePage, pBlobEncoding).ThrowOnFailure(); } public unsafe void CreateBlobWithEncodingOnHeapCopy(void* pText, uint size, winmdroot.Graphics.Direct3D.Dxc.DXC_CP codePage, winmdroot.Graphics.Direct3D.Dxc.IDxcBlobEncoding** pBlobEncoding) { ((delegate *unmanaged [Stdcall])lpVtbl[7])((IDxcLibrary*)Unsafe.AsPointer(ref this), pText, size, codePage, pBlobEncoding).ThrowOnFailure(); } public unsafe void CreateBlobWithEncodingOnMalloc(void* pText, winmdroot.System.Com.IMalloc* pIMalloc, uint size, winmdroot.Graphics.Direct3D.Dxc.DXC_CP codePage, winmdroot.Graphics.Direct3D.Dxc.IDxcBlobEncoding** pBlobEncoding) { ((delegate *unmanaged [Stdcall])lpVtbl[8])((IDxcLibrary*)Unsafe.AsPointer(ref this), pText, pIMalloc, size, codePage, pBlobEncoding).ThrowOnFailure(); } public unsafe void CreateIncludeHandler(winmdroot.Graphics.Direct3D.Dxc.IDxcIncludeHandler** ppResult) { ((delegate *unmanaged [Stdcall])lpVtbl[9])((IDxcLibrary*)Unsafe.AsPointer(ref this), ppResult).ThrowOnFailure(); } public unsafe void CreateStreamFromBlobReadOnly(winmdroot.Graphics.Direct3D.Dxc.IDxcBlob* pBlob, winmdroot.System.Com.IStream** ppStream) { ((delegate *unmanaged [Stdcall])lpVtbl[10])((IDxcLibrary*)Unsafe.AsPointer(ref this), pBlob, ppStream).ThrowOnFailure(); } public unsafe void GetBlobAsUtf8(winmdroot.Graphics.Direct3D.Dxc.IDxcBlob* pBlob, winmdroot.Graphics.Direct3D.Dxc.IDxcBlobEncoding** pBlobEncoding) { ((delegate *unmanaged [Stdcall])lpVtbl[11])((IDxcLibrary*)Unsafe.AsPointer(ref this), pBlob, pBlobEncoding).ThrowOnFailure(); } public unsafe void GetBlobAsUtf16(winmdroot.Graphics.Direct3D.Dxc.IDxcBlob* pBlob, winmdroot.Graphics.Direct3D.Dxc.IDxcBlobEncoding** pBlobEncoding) { ((delegate *unmanaged [Stdcall])lpVtbl[12])((IDxcLibrary*)Unsafe.AsPointer(ref this), pBlob, pBlobEncoding).ThrowOnFailure(); } internal struct Vtbl { internal delegate *unmanaged [Stdcall] QueryInterface_1; internal delegate *unmanaged [Stdcall] AddRef_2; internal delegate *unmanaged [Stdcall] Release_3; internal delegate *unmanaged [Stdcall] SetMalloc_4; internal delegate *unmanaged [Stdcall] CreateBlobFromBlob_5; internal delegate *unmanaged [Stdcall] CreateBlobFromFile_6; internal delegate *unmanaged [Stdcall] CreateBlobWithEncodingFromPinned_7; internal delegate *unmanaged [Stdcall] CreateBlobWithEncodingOnHeapCopy_8; internal delegate *unmanaged [Stdcall] CreateBlobWithEncodingOnMalloc_9; internal delegate *unmanaged [Stdcall] CreateIncludeHandler_10; internal delegate *unmanaged [Stdcall] CreateStreamFromBlobReadOnly_11; internal delegate *unmanaged [Stdcall] GetBlobAsUtf8_12; internal delegate *unmanaged [Stdcall] GetBlobAsUtf16_13; } private void** lpVtbl; /// The IID guid for this interface. /// {e5204dc7-d18c-4c3c-bdfb-851673980fe7} internal static readonly Guid IID_Guid = new Guid(0xE5204DC7, 0xD18C, 0x4C3C, 0xBD, 0xFB, 0x85, 0x16, 0x73, 0x98, 0x0F, 0xE7); [Guid("E5204DC7-D18C-4C3C-BDFB-851673980FE7"),InterfaceType(ComInterfaceType.InterfaceIsIUnknown),ComImport()] internal interface Interface { [PreserveSig()] unsafe winmdroot.Foundation.HRESULT SetMalloc([Optional] winmdroot.System.Com.IMalloc* pMalloc); [PreserveSig()] unsafe winmdroot.Foundation.HRESULT CreateBlobFromBlob(winmdroot.Graphics.Direct3D.Dxc.IDxcBlob* pBlob, uint offset, uint length, winmdroot.Graphics.Direct3D.Dxc.IDxcBlob** ppResult); [PreserveSig()] unsafe winmdroot.Foundation.HRESULT CreateBlobFromFile(winmdroot.Foundation.PCWSTR pFileName, [Optional] winmdroot.Graphics.Direct3D.Dxc.DXC_CP* codePage, winmdroot.Graphics.Direct3D.Dxc.IDxcBlobEncoding** pBlobEncoding); [PreserveSig()] unsafe winmdroot.Foundation.HRESULT CreateBlobWithEncodingFromPinned(void* pText, uint size, winmdroot.Graphics.Direct3D.Dxc.DXC_CP codePage, winmdroot.Graphics.Direct3D.Dxc.IDxcBlobEncoding** pBlobEncoding); [PreserveSig()] unsafe winmdroot.Foundation.HRESULT CreateBlobWithEncodingOnHeapCopy(void* pText, uint size, winmdroot.Graphics.Direct3D.Dxc.DXC_CP codePage, winmdroot.Graphics.Direct3D.Dxc.IDxcBlobEncoding** pBlobEncoding); [PreserveSig()] unsafe winmdroot.Foundation.HRESULT CreateBlobWithEncodingOnMalloc(void* pText, winmdroot.System.Com.IMalloc* pIMalloc, uint size, winmdroot.Graphics.Direct3D.Dxc.DXC_CP codePage, winmdroot.Graphics.Direct3D.Dxc.IDxcBlobEncoding** pBlobEncoding); [PreserveSig()] unsafe winmdroot.Foundation.HRESULT CreateIncludeHandler(winmdroot.Graphics.Direct3D.Dxc.IDxcIncludeHandler** ppResult); [PreserveSig()] unsafe winmdroot.Foundation.HRESULT CreateStreamFromBlobReadOnly(winmdroot.Graphics.Direct3D.Dxc.IDxcBlob* pBlob, winmdroot.System.Com.IStream** ppStream); [PreserveSig()] unsafe winmdroot.Foundation.HRESULT GetBlobAsUtf8(winmdroot.Graphics.Direct3D.Dxc.IDxcBlob* pBlob, winmdroot.Graphics.Direct3D.Dxc.IDxcBlobEncoding** pBlobEncoding); [PreserveSig()] unsafe winmdroot.Foundation.HRESULT GetBlobAsUtf16(winmdroot.Graphics.Direct3D.Dxc.IDxcBlob* pBlob, winmdroot.Graphics.Direct3D.Dxc.IDxcBlobEncoding** pBlobEncoding); } } } } ```

Note how CreateBlobWithEncodingOnHeapCopy returns void and not HRESULT (which is just discarded implicitly).

Expected behavior

The method should have the same signature as indicated in the docs.

Repro steps

  1. NativeMethods.txt content:

    DxcCreateInstance
    IDxcCompiler
    IDxcLibrary
    IDxcIncludeHandler
    CLSID_DxcCompiler
  2. NativeMethods.json content (if present):

    {
    "$schema": "https://aka.ms/CsWin32.schema.json",
    "allowMarshaling": false,
    "useSafeHandles": false
    }
  3. Any of your own code that should be shared?

Don't think so, but anyway all my code is at https://github.com/Sergio0694/ComputeSharp/tree/dev/reflection-tweaks.

Context

Sergio0694 commented 8 months ago

Actually this seems to happen with a bunch of APIs. Eg. IDxcLibrary.CreateIncludeHandler is also bugged.

Perksey commented 8 months ago

I think the design is to automatically throw the exception for the HRESULT (see .ThrowOnFailure(), it is not discarded) so that you only have one exception handling model in the loop in your C# code, I believe this is best addressed by your other issue #976

Perksey commented 8 months ago

Also see PreserveSig, allowing you to preserve the original signature rather than making it "csharp-y". Sources:

It sounds like, given you're used to TerraFX, you want to just use:

{
    "comInterop": {
        "preserveSigMethods": [
            "*"
        ]
    }
}
Sergio0694 commented 8 months ago

Ooops, missed that one, I thought disableMarshalling would be enough to just get 1:1 blittable bindings 😅 Thank you!

AArnott commented 8 months ago

I'm glad you found what you were looking for. Blittability applies to structs -- not COM interface method behavior.