ClangSharp icon indicating copy to clipboard operation
ClangSharp copied to clipboard

Unsupported declaration: 'ClassTemplatePartialSpecialization'

Open uberhalit opened this issue 4 years ago • 4 comments

It appears that we can not create bindings for a template like this:

template<typename T>
struct ObjContainer<T, void, void> { }

ClangSharpPInvokeGenerator throws an error:

Diagnostics for binding generation:
    Error (Line 15, Column 8 in ./test.hpp): Unsupported declaration: 'ClassTemplatePartialSpecialization'. Generated bindings may be incomplete.

uberhalit avatar Nov 19 '21 22:11 uberhalit

This is somewhat expected. Not all C/C++ code has a direct equivalent in C# and so they have to be special cased with alternatives and there are tons of patterns that simply aren't handled today.

Templates in particular are massively complex to support and are only available experimentally today and only if -config generate-template-bindings is specified.

The closest you can get is generics, but due to many ways that they differ its simply not possible to map many of the cases to C# automagically.

tannergooding avatar Nov 21 '21 17:11 tannergooding

I hit this too, with and without --config generate-template-bindings so it's not clear if that works. (Maybe outdated comment?)

> git clone https://github.com/riverar/repro-29005f7a7a48rs
> cd repro-29005f7a7a48rs
> clangsharppInvokeGenerator --config generate-template-bindings -f repro.h -n Repro -o repro.cs

Processing 'repro.h'
Diagnostics for binding generation of repro.h:
    Warning (Line 31, Column 37 in C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Tools/MSVC/14.37.32822/include/xtr1common): Unsupported attribute: 'WarnUnusedResult'. Generated bindings may be incomplete.
    Error (Line 9, Column 8 in repro.h): Unsupported declaration: 'ClassTemplatePartialSpecialization'. Generated bindings may be incomplete.

> type repro.cs
using System.Runtime.InteropServices;

namespace Repro
{
    [NativeTypeName("struct XyzIsFunctionPointer : std::false_type")]
    public partial struct XyzIsFunctionPointer
    {
        [DllImport("", CallingConvention = CallingConvention.ThisCall, EntryPoint = "??B?$integral_constant@_N$0A@@std@@QEBA_NXZ", ExactSpelling = true)]
        [return: NativeTypeName("std::integral_constant<bool, false>::value_type")]
        public static extern byte ToBoolean(XyzIsFunctionPointer* pThis);

        [DllImport("", CallingConvention = CallingConvention.ThisCall, EntryPoint = "??R?$integral_constant@_N$0A@@std@@QEBA_NXZ", ExactSpelling = true)]
        [return: NativeTypeName("std::integral_constant<bool, false>::value_type")]
        public static extern byte operator()(XyzIsFunctionPointer* pThis);
    }

    public static partial class Methods
    {
        [DllImport("", CallingConvention = CallingConvention.Cdecl, EntryPoint = "", ExactSpelling = true)]
        public static extern void Test();
    }
}

riverar avatar Aug 25 '23 23:08 riverar

@tannergooding so to get around this I guess we manually implement them?

elachlan avatar Sep 13 '23 00:09 elachlan

@elachlan. That's probably the only way.

Templates are not equivalent to Generics and there are many concepts that are effectively unrepresentable or not possible (at least not without very hacky workarounds).

The easiest thing is to take such cases and manually port them.

tannergooding avatar Sep 18 '23 16:09 tannergooding