Open imaras opened 1 year ago
If I modify my header file to define CS_IGNORE and I apply it on a class level generation still fails.
#ifndef MY_HEADER_H
#define MY_HEADER_H
#define CS_IGNORE
#include <cstdint>
#include <variant>
class CS_IGNORE my_variant_wrapper
{
public:;
my_variant_wrapper(float result) :
m_Result(result)
{
}
my_variant_wrapper(uint8_t errorCode) :
m_Result(errorCode)
{
}
private:
std::variant<float, uint8_t> m_Result;
};
#endif
I also encountered the same error, also about std::variant
Is there any feedback for this?
Running into this one now, so yeah... Guess I'll fix this one too haha.
Minimal repro:
template<typename X>
class SpecializedTemplateReferencingChildStruct;
template<typename R>
class SpecializedTemplateReferencingChildStruct<R*> {
struct Bar {
R xyzzy;
};
Bar baz;
};
class C {
SpecializedTemplateReferencingChildStruct<int*> a;
};
Root cause of the error is here.
The code tries to look for Bar
in the template, but because Bar
is dependent on R
the declaration is instead in the specialization itself.
This code is in general also not very resilient: it only checks the direct parent for specializations.
If I modify the template a bit to look like this instead:
template<typename X>
class SpecializedTemplateReferencingDeepChildStruct;
template<typename R>
class SpecializedTemplateReferencingDeepChildStruct<R*> {
struct Goo {
struct Bar {
bool xyzzy;
};
};
typename Goo::Bar baz;
};
class D {
SpecializedTemplateReferencingDeepChildStruct<int*> a;
};
Then the GetSuffixForInternal
function will immediately quit through the specialization == null
shortcut, because the specialization is actually 2 levels up. It should walk the whole list of parents instead.
Ok, this issue seems quite a bit more complex than that other one, so I'm going to post a small update here:
Ideally, I wanted to solve this issue by calling getTemplateInstantiationPattern in Clang during the initial parse and storing the result on the Class
node, so that the actual correct original template as known by Clang can be referenced directly. However, I had the native code set up and then realized I have no idea how to regenerate the parser bindings. Tried running Cpp.Parser.Bootstrap.exe
in the bin
directory but that crashes when it can't find llvm/Support/TrailingObjects.h
.
So at the moment I'm using a hack that does "solve" the issue:
public static string GetSuffixForInternal(Class @class)
{
var specialization = @class.GetParentSpecialization();
if (specialization == null)
return string.Empty;
Class template = @class == specialization
? specialization.TemplatedDecl.TemplatedClass
: specialization.FindNestedClass(@class.Name) ?? specialization.TemplatedDecl.TemplatedClass.FindNestedClass(@class.Name);
if (template.HasDependentValueFieldInLayout())
{
if (specialization.Arguments.All(
a => a.Type.Type?.IsAddress() == true))
return "_Ptr";
return GetSuffixFor(specialization);
}
return string.Empty;
}
but is obviously really fragile as well. If the search back down into the AST tree finds another class with the same name first it will incorrectly take that one.
However, even though it doesn't crash anymore now, the code it generates is still faulty:
namespace test
{
namespace SpecializedTemplateReferencingChildStruct
{
[StructLayout(LayoutKind.Sequential, Size = 4)]
public unsafe partial struct __Internal
{
internal global::test.SpecializedTemplateReferencingChildStruct.Bar.__Internal baz;
}
}
// implementation of C...
}
It doesn't generate anything for Bar
at all, so it seems like CppSharp in general has trouble with this kind of construct?
To re-generate the parser bindings you should use https://github.com/mono/CppSharp/blob/main/src/CppParser/ParserGen/ParserGen.cs.
https://github.com/mono/CppSharp/releases/download/CppSharp/headers.zip is also necessary to generate bindings for all platforms.
It doesn't generate anything for
Bar
at all, so it seems like CppSharp in general has trouble with this kind of construct?
Yep, template support in general still has some issues.
To re-generate the parser bindings you should use https://github.com/mono/CppSharp/blob/main/src/CppParser/ParserGen/ParserGen.cs.
https://github.com/mono/CppSharp/releases/download/CppSharp/headers.zip is also necessary to generate bindings for all platforms.
It doesn't generate anything for
Bar
at all, so it seems like CppSharp in general has trouble with this kind of construct?Yep, template support in general still has some issues.
Having another look at this. @tritao Could you please explain to me the rationale behind collapsing all internal structs for specializations that only have pointers as template parameters? It seems logical since IntPtr
is used for all pointers, but it also seems to only handle one very specific case and it's hard to calculate the postfixes for complex templates.
To re-generate the parser bindings you should use https://github.com/mono/CppSharp/blob/main/src/CppParser/ParserGen/ParserGen.cs. https://github.com/mono/CppSharp/releases/download/CppSharp/headers.zip is also necessary to generate bindings for all platforms.
It doesn't generate anything for
Bar
at all, so it seems like CppSharp in general has trouble with this kind of construct?Yep, template support in general still has some issues.
Having another look at this. @tritao Could you please explain to me the rationale behind collapsing all internal structs for specializations that only have pointers as template parameters? It seems logical since
IntPtr
is used for all pointers, but it also seems to only handle one very specific case and it's hard to calculate the postfixes for complex templates.
Pretty much all of template support was done by @ddobrev, who unfortunately is no longer with us, so I really cannot tell what the rationale was for that decision. Feel free to propose changes to it to fix any issues and we can get them merged.
Brief Description
C# code generation for header file my_header.h
fails with System.NullReferenceException.
Console output is:
OS: Windows