bottlenoselabs / c2cs

Generate C# bindings from a C header.
MIT License
250 stars 18 forks source link

Source generators #83

Closed lithiumtoast closed 2 years ago

lithiumtoast commented 2 years ago

Been experimenting with source generators; they do work and are very cool. The benefit of source generators is that it allows C2CS to be a "plugin" to the Rosyln compiler. It would run at build time for each project and add the generated source code to the final compilation. For this project itself, this would be beneficial for building the examples as it would make them smoke tests which can be executed via GitHub actions. It would then be immediately obvious if any the examples are broken.

Problems:

  1. Rider has some visual hiccups with generated code not being displayed (building the project in Rider works fine, but intellisense doesn't work.) I expect JetBrains to iron out these issue over time. Rider uses a completely different engine for C# and thus always lags behind a bit on bleeding edge or fairly new features of C#. For this reason alone, source generators are in my opinion not ready for prime time.

  2. Source generators have to target .netstandard2.0. C2CS uses bindings for libclang with some callbacks to C# from C which the UnmanagedCallersOnly attribute is used. This attribute is not available in .netstandard2.0, it was introduced in .net5.0. Callbacks to C# from C have to fallback to using Marshal.GetFunctionPointerForDelegate to which completely eliminates the benefit of using C# function pointers. This is the exact problem for https://github.com/bottlenoselabs/c2cs/issues/67 to which this is not a deal breaker for C2CS to use source generators per se from a technical perspective. However it is annoying; I rather keep C2CS on the train of .NET Core/5/6/7 because it gives me an excuse to learn and play with the latest iterations of .NET. The work around I have been doing for now is to execute C2CS from command line as a .net6.0 application from a .netstandard2.0 source generator context. Which goes into the next problem...

  3. Source generators are ripe for opening of the possibility of malware/spyware/etc. Because source generators are essentially a plugin to the Rosyln compiler, a developer would be running some C# code at build time. When you open up a project in Rider for the first time it asks you "do you trust this project?". That message totally makes sense to me now because anyone could clone down a Git repository of some C# code and open it up with Rider to which building the project could be executing code you may or may not trust completely. Since I execute the .net6.0 version of C2CS by running a new process from the .netstandard2.0 source generator as a work around to problem 2 above, it becomes clear that if someone were to switch out the path for c2cs they would then be running their own swapped out program. This sounds risky as it opens up the door to abuse. Running C2CS once to generate the bindings may be an extra step that could be automated away with source generators but that seems rather foolish as the benefits of source generators for C2CS in my honest opinion don't seem to be worth that risk. To be clear, source generators do solve specific problems to which the benefits out weight the risks, but in the context of C2CS I don't believe this to be the case.

lithiumtoast commented 2 years ago

Decided not to pursue source generators for the reasons listed above.