Closed zer0n closed 4 years ago
ABI between C++/CLI and .NET
It is fairly simple actually:
@weltkante Take a look in the C/C++ compiler: https://github.com/LADSoft/OrangeC , OrangeC has a back-end to compile C to MSIL
@richlander Previously, C++/CLI .NET Framework assemblies compiled with MVCC using /clr:pure would work fine on Linux. Since you seem to be in the know, would you be able to fill us in on why this functionality was removed from VS2017? What steps are being taken to restore the ability to compile cross-platform C++/CLI assemblies?
@richlander i agree regarding how challenging linux support is. Although i remember Mono developers' experience - they managed to implement most .net framework (without wpf though), seemingly with c++/cli support. And .net already uses mono in their code. So maybe you shouldnt implement c++/cli yourself and just describe (if thats not done yet) how to create mixed mode assemblies, so compiler developers could eventually implement that themselves?
Lets imagine an llvm-based compiler for mixed mode assemblies. Not specifically c++. Just a compiler. It could produce assemblies with pieces of embedded llvm bitcode which is then compiled (on building machine) into assemblies for target architectures and platforms. .net build tool could then simply require such tools to create a json file somewhere which tells how to create and compile assemblies for each platform. Done. For developers the whole installation process will look as installing .net core sdk and the described compiler. Then he could just say in his csproj/whatever that he wants to compile files which match the wildcard in this language, with any compiler which implements that. This could also allow mixing multiple languages into single project though: like c++, rust, c#, etc.
@SwooshyCueb cross platform C++/CLI is currently not planned
@bencz sorry if I'm mistaken, but this sounds as if it was just a C language frontend with a IL language backend? This would be exactly what I'm not looking for, what I'm interested in is how native code is integrated into the managed framework (and vice versa), only the Microsoft C++/CLI compiler has this integration to produce mixed mode assemblies as far as I know.
@jkotas Thanks for those pointers, but I think there is more to it considering that C++/CLI is hardwired against the CLR, which wouldn't be necessary if there were no additional assumptions in the ABI. I definitely remember reading that C++/CLI makes use of memory layout assumptions e.g. of arrays and strings, probably more assumptions exist. This is the kind of interop I'm interested in since its what allows you to make deep and fast integration between native and managed. Maybe there aren't really many assumptions, but its always been a black box, so documenting the contract C++/CLI requires to work would be nice (and IMHO an important first step to have 3rd party implementations possible)
Maybe some of this is already documented (its been a long time since I last looked at the BOTR and coreclr documentation to be honest, so I don't remember exactly what it includes) but I still think there is value in having it documented centrally, both for people who want to develop third party integration and also for coreclr itself. Documenting which assumptions must be kept intact when moving coreclr forward to not break C++/CLI integration sounds useful in itself. (And if the contracts change and C++/CLI has to be updated, this documentation would be a central resource to watch by 3rd party developers to update their integration as well.)
C++/CLI makes use of memory layout assumptions e.g. of arrays and strings,
It makes the same assumptions as what you can make in portable unsafe C#. There is no magic above that.
is is the kind of interop I'm interested in since its what allows you to make deep and fast integration between native and managed.
C++/CLI does not have any fundamental performance advantage over regular PInvoke and unsafe C#. It is pretty much always possible to rewrite C++/CLI in C# and get same performance characteristics. (The notable exception are function pointers that are not available in C# today, but that is getting fixed for C# 9.)
The advantage of C++/CLI is that makes it easy to write interop code. It saves you from doing bug-prone translation of signatures from C/C++ to C#.
@jkotas
C++/CLI does not have any fundamental performance advantage over regular PInvoke and unsafe C#.
The Microsoft documentation on this seems to suggest otherwise. They refer to implicit vs explicit PInvoke and the implicit PInvoke refers you to C++/CLI (C++ Interop). In the wording for implicit PInvoke it is mentioned more than once that implicit PInvoke is more performant.
Perhaps this is a mistake in the documentation that should be remedied.
This is the documentation I'm referencing: https://docs.microsoft.com/en-us/cpp/dotnet/calling-native-functions-from-managed-code?view=vs-2019
@xgalaxy The reason for the performance gain is also stated in that documentation:
The IJW mechanism is slightly faster (for example, the IJW stubs do not need to check for the need to pin or copy data items because that is done explicitly by the developer).
You could do the same tricks in PInvoke, but you don't need to.
@jkotas
The advantage of C++/CLI is that makes it easy to write interop code. It saves you from doing bug-prone translation of signatures from C/C++ to C#.
Microsoft develops another tool that does this: https://github.com/mono/cppsharp
It seems clear that C++/CLI will not be supported cross platform. So, I think what C++/CLI developers need is tool that allows us from transition away from C++/CLI to C#. Perhaps, the msvc compiler could output C# when compiling C++/CLI code.
Perhaps this is a mistake in the documentation that should be remedied.
I have submitted https://github.com/MicrosoftDocs/cpp-docs/pull/1822 to correct it.
tool that allows us from transition away from C++/CLI to C#
It is hard/impossible to do write a tool like this. C# does not have the same expressive power as C++.
There are tools available that try to do a best effort to do that, e.g. https://www.tangiblesoftwaresolutions.com/product_details/cplusplus_to_csharp_converter_details.html . Read the FAQ for this tool - it talks a lot about manual adjustments required after the conversion.
@jkotas I think what @szilvaa wants would be more like a tool that takes C++/CLI a gives the equivalent C# with P/Invoke and C++ code.
@jkotas Thank you for your comments! I appreciate your attention.
I'm not interested in converting C++ code to C# in general. I'm interested in converting .net bindings written in C++/CLI to C#. Building these bindings has always been the sweet spot for C++/CLI and I suspect that the majority of the usage falls into this category.
These users are now stranded. They can't move their code to non-windows platforms without rewriting.
It is hard/impossible to do write a tool like this. C# does not have the same expressive power as C++.
This is probably true in the general case but I don't think anybody is interested in the general case or even a perfect solution. I'm interested in a "good enough" solution that converts "common case" C++/CLI to C#. Something slightly better than what I can do today by compiling my C++/CLI code to IL and then decompiling the IL to C#.
Note, my code is old enough that it actually started out as managed C++. Back then, the C++ team provided a tool to help the transition to C++/CLI! https://devblogs.microsoft.com/cppblog/managed-extensions-for-c-to-ccli-conversion-tool/
I'm facing yet another transition, Microsoft is in a unique position to help here because they have the only production C++/CLI parser in the world.
There are tools available that try to do a best effort to do that, e.g. https://www.tangiblesoftwaresolutions.com/product_details/cplusplus_to_csharp_converter_details.html . Read the FAQ for this tool - it talks a lot about manual adjustments required after the conversion.
This tool does not work at all with C++/CLI code.
These users are now stranded. They can't move their code to non-windows platforms without rewriting.
This affects Paint.NET and has been seriously frustrating, as C++/CLI really is the perfect tool for this type of work. Everything else I've investigated has had major drawbacks.
The compiler's deprecated, I get that, but at least give us something so we can get out of this corner we've all been painted into.
@szilvaa, maybe you'd like to take a look at SharpGenTools: this is a (production-ready) generator for .NET bindings from C/C++ code. It could replace C++/CLI in this role in some (most?) of the scenarios.
@ForNeVeR Thanks for the pointer. Good to know. However, I already have tens of thousands of lines of C++/CLI code. I'd rather not abandon these existing .net bindings. I'd like to migrate them forward.
@szilvaa Given the state of the world, your best bet to make your bindings cross-platform are:
I know that this is not the answer you were hoping for, but hope it helps.
I'm not sure whether this is the appropriate repo to ask this question. If not, please advise the correct one.
I want to do .NET development in Linux. I haven't been able to do it yet due to lack of important features in Mono. One of them is C++/CLI. I wonder whether and/or when this will be available soon.