-
Notifications
You must be signed in to change notification settings - Fork 153
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rewrite the ClangSharpPInvokeGenerator to allow better reuse and to be more explicit #34
Conversation
|
||
switch (name) | ||
{ | ||
case "size_t": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hopefully a better can be solved to handle this and other similar types... Potentially could check for both regular and -m32
mode and if it differs chooise IntPtr
, that way it is more general....
|
||
namespace ClangSharpPInvokeGenerator | ||
{ | ||
internal static class CXTypeExtensions |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the writer is extended to support user-configuration, these might need to either take additional parameters or become instance methods on the writer... The later might be better since they are more specific to the writer than to the actual interop types.
|
||
case CXTypeKind.CXType_Char_S: | ||
{ | ||
return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could be LPUTF8Str
if we said net48
, netstandard2.1
, and netcoreapp10
are the baseline
|
||
case CXCursorKind.CXCursor_ParmDecl: | ||
{ | ||
if (cursor.Type.GetParmModifier(cursor).Equals("out")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is probably a better way to handle this combination...
} | ||
} | ||
|
||
public static string GetParmModifierForPointeeType(this CXType type, CXCursor cursor, CXType pointeeType) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could also support in
and ref
for "safe" code. Part of the problem, however, is that if attributes don't exist we are just guessing and will often get it wrong....
@@ -158,31 +158,38 @@ public static void Main(string[] args) | |||
sw.WriteLine(" using System.Runtime.InteropServices;"); | |||
sw.WriteLine(); | |||
|
|||
var structVisitor = new StructVisitor(sw); | |||
var structDeclWriter = new CursorWriter(sw, indentation: 1, (cursor) => cursor.Kind == CXCursorKind.CXCursor_StructDecl); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could potentially expose a method that takes the predicate, rather than the constructor, so you can reuse the instance across multiple filters...
sw.WriteLine($" private const string libraryPath = \"{libraryPath}\";"); | ||
sw.WriteLine(); | ||
|
||
functionDeclWriter.PrefixStrip = prefixStrip; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally there would be a better way to pass this, and other options, in. Potentially a CursorWriterOptions
type....
I'll get a fix up that resolves the couple issues I called out in an hour or two. |
@tannergooding Sounds good. Now that it's SDK style, I'm thinking we can make it all nice like other dotnet repos with Azure DevOps and analyzers! I did want to ask you about if we were to make these signed nuget packages what secret sauce the dotnet repos have. We can have that conversation offline if need be. |
… launchSettings to be machine independent
Dependency on S.R.CompilerServices.Unsafe was removed. Fixed the launchSettings.json to include a Unix profile and to not be machine dependent. It still makes an assumption about the location of LLVM and assumes it is running from the current output directory (which is how VS runs it for F5).
That would be nice. It could potentially be use |
The F5 is important so that's good. I'm wondering if we could do a download of LLVM-* and have it be there as part of the build. It's cached for most scenarios, but it'll allow us the latest and greatest. I'm now eyeing how we can improve LLVMSharp with this rewrite. I've been bogged down with issues in the generator and now at least somethings seem better that it could be 100% generated without modifications. I did have a question. It is my understanding that a single IntPtr in a struct for marshalling can't be ABI incompatobe. But you said it is, are there examples? |
It might be possible, but it's also a 350 MB tarball which might be more than some people expect (especially if they already have it locally). Probably worth some further thought to determine the right behavior...
Struct wrappers are generally not a problem for most ABIs. However, |
For reference on the |
That's Great! I'm going to try out a few more libraries after this is merged and try to ensure more scenarios are covered as well as there are likely plenty of cursor types that still need to be handled. |
Are you waiting for me to merge? Or is there is more to be done here? |
Nothing more to be done here. Was waiting to ensure nothing else came up from the conversation above. |
I imagine there will be some feedback and/or questions that need to be addressed, so feel free 😄
This rewrites the ClangSharpPInvokeGenerator code. For the most part, the rewrite tries to produce code that is nearly identical to the previous codegen.
An overview is:
CursorVisitor
and extension pointsBeginHandle
andEndHandle
are exposed, to make it easy for someone to handle or skip particular nodes and to execute their own code.CursorWriter
. It takes aFunc<CXCursor, bool>
predicate that allows a user to indicate if they want to process or skip a given node. The visitation logic should account for nested types and for nodes that always need to be traversedThe notable changes are:
Location.IsInMainFile
, this ultimately means the order is slightly different and that we don't visit#includes
. This changes the output order slightly but also means we don't need to keep track of already visited nodes.uint
foruint
rather thanint
@
to everything, and instead only prefix it to reserved C# keywordspublic CXCompletionString CompletionString
rather thanpublic IntPtr @CompletionString
. The latter (IntPtr
) will still be done if there is a double indirection.: int
, since that is the defaultIntPtr
rather thanulong
forsize_t
, to make the code produced more portablePotential Future changes:
Span<T>
, that make it much easier to work with unsafe typessingle vs multi-file generation
andsafe vs unsafe generation
) and others likeAnyCPU vs Platform Specific generation
orWindows vs Unix
generation (for handling thelong
isIntPtr
vsint
problem)