CppSharp icon indicating copy to clipboard operation
CppSharp copied to clipboard

C# Code generation fails in GenerateFieldGetter method

Open imaras opened this issue 2 years ago • 5 comments

Description

If I try to generate C# code from:

class my_optional_u32
{
public:
    my_optional_u32() 
    {
        m_Object = {};
    }

    void set_value(uint32_t value) 
    {
        m_Object = value;
    }

    void set_null() 
    {
        m_Object = {};
    }

    uint32_t value() 
    {
        return m_Object.value();
    }

    bool has_value() 
    {
        return m_Object.has_value();
    }

private:
    std::optional<uint32_t> m_Object;
};

struct my_struct
{
    uint16_t Property1;
    uint16_t Property2;
    uint8_t Property3;
    my_optional_u32 Property4;
};

generation fails in https://github.com/mono/CppSharp/blob/main/src/Generator/Generators/CSharp/CSharpSources.cs line 1366

var name = ((Class)field.Namespace).Layout.Fields.First( f => f.FieldPtr == field.OriginalPtr).Name;

when generating property getter for field Property1. Collection Fields contains no elements.

OS: Windows

Used headers

optional

imaras avatar Mar 03 '23 10:03 imaras

Thanks for reporting this.

tritao avatar Mar 06 '23 09:03 tritao

I've managed to fix the issue by adding line bellow in Setup method

driver.ParserOptions.LanguageVersion = LanguageVersion.CPP17_GNU;

Reason why this is fix for the reported issue is that if LanguageVersion is unspecified in the process of code generation it gets set to LanguageVersion.CPP14_GNU and optional is not supported by this C++ version, as can be seen from https://en.cppreference.com/w/cpp/header/optional.

imaras avatar Mar 08 '23 09:03 imaras

If you don't mind I'll keep this open in the meanwhile, since we should not be crashing regardless.

tritao avatar Mar 08 '23 09:03 tritao

Reason why this is fix for the reported issue is that if LanguageVersion is unspecified in the process of code generation it gets set to LanguageVersion.CPP14_GNU and optional is not supported by this C++ version, as can be seen from

I think if that was the case, shouldn't you have gotten a parser error instead?

tritao avatar Mar 08 '23 09:03 tritao

Printing parser error would be the way to go. At the moment exception call stack is printed.

Parsing libraries...
Parsed 'mylibrary.dll'
Parsing code...
Parsed 'myheader.h, optional'
Processing code...
Generating code...
Unhandled exception. System.InvalidOperationException: Sequence contains no matching element
   at System.Linq.ThrowHelper.ThrowNoMatchException()
   at System.Linq.Enumerable.First[TSource](IEnumerable`1 source, Func`2 predicate)
   at CppSharp.Generators.CSharp.CSharpSources.GenerateFieldGetter(Field field, Class class, QualifiedType returnType)
   at CppSharp.Generators.CSharp.CSharpSourcesExtensions.GenerateField(CSharpSources gen, Class class, Field field, Action`3 generate, Boolean isVoid)
   at CppSharp.Generators.CSharp.CSharpSources.GeneratePropertyGetter[T](T decl, Class class, Boolean isAbstract, Property property)
   at CppSharp.Generators.CSharp.CSharpSources.GenerateProperties(Class class)
   at CppSharp.Generators.CSharp.CSharpSources.GenerateClassProperties(Class class)
   at CppSharp.Generators.CSharp.CSharpSources.VisitClassDecl(Class class)
   at CppSharp.AST.Class.Visit[T](IDeclVisitor`1 visitor)
   at CppSharp.Generators.CSharp.CSharpSources.VisitDeclContext(DeclarationContext context)
   at CppSharp.Generators.CodeGenerator.VisitNamespace(Namespace namespace)
   at CppSharp.Generators.CSharp.CSharpSources.VisitNamespace(Namespace namespace)
   at CppSharp.AST.Namespace.Visit[T](IDeclVisitor`1 visitor)
   at CppSharp.Generators.CSharp.CSharpSources.VisitDeclContext(DeclarationContext context)
   at CppSharp.Generators.CodeGenerator.VisitNamespace(Namespace namespace)
   at CppSharp.Generators.CSharp.CSharpSources.VisitNamespace(Namespace namespace)
   at CppSharp.AST.Namespace.Visit[T](IDeclVisitor`1 visitor)
   at CppSharp.Generators.CSharp.CSharpSources.VisitDeclContext(DeclarationContext context)
   at CppSharp.Generators.CodeGenerator.VisitNamespace(Namespace namespace)
   at CppSharp.Generators.CSharp.CSharpSources.VisitNamespace(Namespace namespace)
   at CppSharp.Generators.CodeGenerator.VisitTranslationUnit(TranslationUnit unit)
   at CppSharp.AST.TranslationUnit.Visit[T](IDeclVisitor`1 visitor)
   at CppSharp.Generators.CSharp.CSharpSources.Process()
   at CppSharp.Generators.Generator.GenerateModule(Module module)
   at CppSharp.Generators.Generator.Generate()
   at CppSharp.Driver.GenerateCode()
   at CppSharp.ConsoleDriver.Run(ILibrary library)
   at Program.<Main>$(String[] args)

imaras avatar Mar 08 '23 09:03 imaras