Runtime: Will CoreCLR support C++/CLI crossplat?

Created on 7 Apr 2015  Â·  66Comments  Â·  Source: dotnet/runtime

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.

area-Interop-coreclr question

Most helpful comment

I understand that. But in reality, failing to do so is dooming C++/CLI. It doesn't even support talking to C# classes that use generics in certain ways; the level of utility is quite low. There should be an honest discussion about its future.

All 66 comments

@zer0n I can't predict what the long game is but our current focus is C# and VB scenarios for cross plat. Modifying title in case someone else would like to chime in.

@richlander may have some other thoughts but he's on vacation til next week.

There is no plan to support C++/CLI with .NET Core. It requires features in the CLR, the C++ compiler and the C-Runtime. It also adds a significant cost to the porting cost to port the entire .NET Core feature set to a new chip. While C++/CLI is indeed useful, it's cost profile is prohibitive. We have a lot to do still to provide excellent support for regular IL on Linux and OS X. That's where we want to focus our time and effort.

We'd be OK with someone else taking on this project, however, I'd put it under the "hard problems" umbrella (label added).

Understood. I didn't know that it was that much work. I thought that it was simply opening and cleaning up the .NET on Windows stack.

@richlander If MS is ok with someone else taking it on, are you guys willing to document and/or open source some of the required bits to the compiler and runtime, or is that off the table?

EDIT: To clarify, open source a-la reference source, not in a maintained supported fashion.

@kangaroo I suspect that the CLR parts that are needed are already present in the coreclr repository but under #ifdefs.

Anyway, the real problem is the C++ compiler, not the runtime. The mixed mode images produced by VC++ will contain native code that targets Windows. So you'll need to either convince them to open source the VC++ compiler so it can ported to other platforms or convince the clang and/or gcc guys to add support for C++/CLI. Not going to happen :smile:

@mikedn I fully understand the scope and problem of the question :) It was more a clarification and optics push, rather than a "I want this".

I know, I know, I was just trying to clarify your clarification for other readers who perhaps don't see clear enough :)

Thanks guys for the multi-level clarification :).

@mikedn Thanks for clarifying my clarification of the clarification... or something :+1: #clrinception

Given the current (poor) stability level of C++/CLI on windows, what is there to lose by open-sourcing it so the community can help with maintenance?

@nathanaeljones - I suspect that @mikedn's point on this is the one to pay attention to. The VC++ team would need to open source either all or part of the VC++ compiler. I don't believe that's on their roadmap right now. They are focussed on other projects. I don't think we'll be able to convince them otherwise.

I understand that. But in reality, failing to do so is dooming C++/CLI. It doesn't even support talking to C# classes that use generics in certain ways; the level of utility is quite low. There should be an honest discussion about its future.

Perhaps, but given the general reluctance of people outside of the Mono Project/Xamarin to even consider using any CLR based language to begin with, there may not be enough justification for the effort expended at this time. I'm using C# for my Linux and Mac OS projects because the development team I'm working with to do this work is using .NET for their Windows based applications and my code will run on all platforms once written.

The end result being to be able to write std portable C++ code (compile with CLR disabled for files with C++11/14 code) and wrap it with thin CLR layer to be able to consume in .NET application. At least this way we are writing standard C++11/14 code today, in conjunction with .NET: the slimmer the CLR code layer is (in favor of std::C++), the better.

gcc guys to add support for C++/CLI. Not going to happen

I think that already happened. ECMA-335 was one of the projects in GCC universe: http://gcc.gnu.org/projects/cli.html#intro. Theoretically, we can compile the CLI code and invoke it with .NET on Unix. Perhaps @gabrielesvelto and @migueldeicaza can further comment on it.

One of the Xamarin developers implemented C++/CLI support in a fork of clang last year: https://github.com/tritao/clang

Nuanti developed their own C++/CLI compiler in a similar fashion: http://www.atoker.com/blog/2012/04/12/llvm-europe-2012-cli-compiler/

I just wanted to point out there are alternatives for C++/CLI's future beyond asking MS to open-source the Visual C++ compiler.

The GCC's CLI back-end was an interesting project I worked on in a past life. IIRC we managed to maintain it until GCC 4.4 after which a lot of people on the team who worked on it were moved to other projects causing the project to halt. The idea was to be able to compile native C (and eventually C++ code) into quasi portable CLR bytecode. We had coverage for most of GCC's C test suite (well north of 95% IIRC) but we hadn't had time to include C++ support. Results on real code also quite encouraging. I remember us running some demo code on top of SDL with everything (including the SDL library) being compiled in CLR. The only portability limitation of the generated code was that pointer sizes of the target machine would be hard-coded in the data structures layout so you needed different code for 32- and 64-bit targets. We also developed a glibc shim and binutils wrappers so that the entire toolchain would work as expected when compiling native code.

Most of the code we added worked straight on top of GIMPLE (disabling the entire RTL back-end while operating) so it shouldn't be too hard to make it work on top of a recent GCC branch.

Today there are no production level implementations of C++/CLI that can suitably be used in the Unix world. There are various attempts, but C++ is a large language, and a mapping to CLI is not exactly simple.

So an opensourced compiler would be great.

I worked with some bindings, about five years ago, where I had integrated the ogre library with the C# code with support for inheritance too, all that with a lot of additional generated stuff to simulate methods overwrite etc. The work was done by generatting c interfaces to wrap the C++ classes at a low level, something like swig, but a little better, almost the same way that the Mono Cpp tool does (that was in the begining at the time), with a difference, in my code the bindings were dinamically defined, and the native library had something like pointer dictionary exported as a C API to match the mangled function's name in C++... Maybe something like that can help to overpass the difference among the C++ ABI of all the compilers.

Just to point out... one of my requirements was portability among Win, Linux and OSX.

@danfma, that is the way to go: providing the ISO C API for the standard C/C++ lib and then P/Invoke (FFI) it from .NET RT. This brings advantages on multiple accounts, for example,

  • your lib is consumable from LuaJIT-FFI, node.js, Ruby-FFI or [m]any language runtime; and not limited to .NET.
  • like you said; to achieve x-platform-ness.

Also, CoreFX is P/Invoking the System.Native libs and it is working out pretty well.

On performance end, P/Invocation is better than C++/CLI wrap: http://www.xinterop.com/index.php/2013/05/01/ccli-vs-pinvoke-performance-part-one/ (I haven't compared the performance myself though but it would be interesting to see varied results).

With this reasoning, IMHO it's better to invest time in improving the P/Invoke internals, seize every optimization opportunity and encourage (force?) people to write better, standard x-plat native code with C/Rust wrapper -- rather than incorporating and appreciating C++/CLI infrastructure in CoreCLR.

Hi
David, creator of OrangeC and C++ compiler are working on a implementation of a new back-end for their compiler, to support code generation for CLR... at now, the compiler can build some complex programs in C to MSIL, like bzip2.
Btw, at now, is just a experimental project, it's not build every C program...

https://github.com/LADSoft/OrangeC
https://github.com/LADSoft/Simple-MSIL-Compiler/

It may be that somebody else is interested in the project :)

Just to complete the referenced issue of mine: enabling the wrapping of C/C++ libraries with PS would render it a viable alternative to Python. Depending on script engine performance, it might even prove to be better.

I created an article in code project talking about the new back end of orangec compiler, We succeeded to compile and use the SQLITE with a C# project, and also we succeeded to compile an older version of a C compiler that David, creator of OrangeC developed.

http://www.codeproject.com/Articles/1128868/Compiling-your-C-code-to-NET

You can see the sqlite test project in this link:
https://github.com/LADSoft/Simple-MSIL-Compiler/tree/master/netil/sqlite3/sqliteil

So, Maybe in a few months, we will compile C++ code.
We are currently developing a lib. to generate the DLL / EXE for .Net, the idea is to create something like this lib: https://github.com/0xd4d/dnlib

Hey @bencz, nice work with OrangeC but maybe this will not fit at this scenario because sometimes we really will want to consume the native library. Some libraries will have platform specific code that can't be compiled to .NET but I think you already know that! ;)

Although, maybe your approach can be used to generate the wrappers and to facilitate the integration of C++ code with C#, like a glue library, generated by the compiler... maybe...

Hi @danfma!
Thanks!!

Yeap, we know that... but, we can't do anything for this case... buuuut for code written in C ANSI, we are re-creating the entire RT of C in a dll, to make it more dynamic. :)
is exactly the idea, facilitate integration between the codes ... reduce as much as possible the number of pInvokes.. :)
One of the next steps will be to compile C++ code, I believe this will be difficult...

Abraço!

Yes. This is highly desirable. working with C++ means performance and .net core is much more performant that .net.

_Disclaimer: apologies if some .NET-related terminology is misused here; I am primarily a C++ developer and the .NET train has not yet hit me hard, since I cannot really meld my own stuff into the .NET world in a portable manner._

One remark/question: it has occurred on multiple occasions that people writing C++ tools argued that name mangling in the C++ world is less than friendly (or portable at least), just as it was mentioned by @danfma.

Here's my 5 cents: wouldn't restricting the interface to C++ Modules solve this issue? Essentially it's pre-compiled headers and binaries packed together with compiler-agnostic decoration to find signatures and symbols inside the PCH and library files. This wouldn't hurt the end-user much, because C++/CLI libraries are already forced into a namespace of their own, leaking defines is not possible (AFAIK, although this feature is currently being discussed through the working draft of the Modules proposal).

I understand that this would mean drawing the minimum line at a C++20 targeted TS, but at least there are 2 converging implementations (MSVC and Clang), which is a fairly good start, plus the purpose of the TS is to gain experience using the feature and bake the final version accordingly.

The module file could also come in handy when one has to generate the manifest file of the resulting assembly.

As I understand the discussion until here, it is not supported to CREATE .Net Core assemblies in C++/CLI.

Is it supported to USE .Net Standard assemblies in C++/CLI?

@t-sch with Mono it's possible to call managed assemblies from unmanaged code. See Embeddinator-400.

Ok!
You can call the .net from unmanaged code too..., using the mscoree function to start the .net machine, look this, as a example: Calling a C# Method from C/C++ (Native Process)

Here is documentation for hosting .net core:

https://docs.microsoft.com/en-us/dotnet/core/tutorials/netcore-hosting

I'm wondering if anyone could provide guidance on wrapping .NET Core assemblies for other platforms.

@danfma & @ghost - You each wrote:

@danfma

I worked with some bindings, about five years ago, where I had integrated the ogre library with the C# code with support for inheritance too, all that with a lot of additional generated stuff to simulate methods overwrite etc. The work was done by generatting c interfaces to wrap the C++ classes at a low level, something like swig, but a little better, almost the same way that the Mono Cpp tool does (that was in the begining at the time), with a difference, in my code the bindings were dinamically defined, and the native library had something like pointer dictionary exported as a C API to match the mangled function's name in C++... Maybe something like that can help to overpass the difference among the C++ ABI of all the compilers.

and @ghost

that is the way to go: providing the ISO C API for the standard C/C++ lib and then P/Invoke (FFI) it from .NET RT. This brings advantages on multiple accounts, for example, your lib is consumable from LuaJIT-FFI, node.js, Ruby-FFI or [m]any language runtime; and not limited to .NET.
like you said; to achieve x-platform-ness.
Also, CoreFX is P/Invoking the System.Native libs and it is working out pretty well.

We are building an SDK that calls some OData endpoints and has a bunch of helper functions in .NET Core, but would like to wrap it for other platforms (python, ruby, etc.). I'm am looking for a good approach to this.

Here is my ruby question on stackoverflow: https://stackoverflow.com/questions/49734820/is-there-a-technique-to-wrap-a-net-core-library-as-a-ruby-gem

A bit off topic but for python <-> .net there is pythonnet interop library
which has working versions with .net core support, but not merged into
Master branch yet.

Reviews from .NET experts are welcome!

https://github.com/pythonnet/pythonnet/issues/96

On Thu, Apr 12, 2018, 8:55 AM philcarbone notifications@github.com wrote:

@danfma https://github.com/danfma & @ghost https://github.com/ghost -
You each wrote:

@danfma https://github.com/danfma

I worked with some bindings, about five years ago, where I had integrated
the ogre library with the C# code with support for inheritance too, all
that with a lot of additional generated stuff to simulate methods overwrite
etc. The work was done by generatting c interfaces to wrap the C++ classes
at a low level, something like swig, but a little better, almost the same
way that the Mono Cpp tool does (that was in the begining at the time),
with a difference, in my code the bindings were dinamically defined, and
the native library had something like pointer dictionary exported as a C
API to match the mangled function's name in C++... Maybe something like
that can help to overpass the difference among the C++ ABI of all the
compilers.

and @ghost https://github.com/ghost

that is the way to go: providing the ISO C API for the standard C/C++ lib
and then P/Invoke (FFI) it from .NET RT. This brings advantages on multiple
accounts, for example, your lib is consumable from LuaJIT-FFI, node.js,
Ruby-FFI or [m]any language runtime; and not limited to .NET.
like you said; to achieve x-platform-ness.
Also, CoreFX is P/Invoking the System.Native libs and it is working out
pretty well.

This was a while ago, but I'm wondering if anyone could provide guidance
on wrapping .NET Core assemblies in other languages. We are building an SDK
that calls some OData endpoints and has a bunch of helper functions in .NET
Core, but would like to wrap it for other platforms (python, ruby, etc.).
I'm am looking for a good approach to this. Here is my ruby question on
stackoverflow:
https://stackoverflow.com/questions/49734820/is-there-a-technique-to-wrap-a-net-core-library-as-a-ruby-gem

—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/dotnet/coreclr/issues/659#issuecomment-380813183, or mute
the thread
https://github.com/notifications/unsubscribe-auth/AHgZ5XaRH6_457OgYAzHFvHhs5dmQ0R3ks5tn1y0gaJpZM4D70Kx
.

I came to this thread searching for answers to how to use .net core for my mixed assembly in C++/CLI.

I understand that there's currently no plan to make C++/CLI available cross-platform. But I only need to use .net core on Windows, and the C++/CLI assembly automatically load .net framework. The element in app config only allows specifiying .net framework, not .net core.

@pongba You can track progress on Windows-only Managed C++ support in dotnet/coreclr#18013. We plan to solve the problem that you are describing by recompiling the managed C++ assembly for .NET Core (the managed C++ compiler that can do this is not available yet).

I'm wondering if anyone could provide guidance on wrapping .NET Core assemblies for other platforms.

@danfma & @ghost - You each wrote:

@danfma

I worked with some bindings, about five years ago, where I had integrated the ogre library with the C# code with support for inheritance too, all that with a lot of additional generated stuff to simulate methods overwrite etc. The work was done by generatting c interfaces to wrap the C++ classes at a low level, something like swig, but a little better, almost the same way that the Mono Cpp tool does (that was in the begining at the time), with a difference, in my code the bindings were dinamically defined, and the native library had something like pointer dictionary exported as a C API to match the mangled function's name in C++... Maybe something like that can help to overpass the difference among the C++ ABI of all the compilers.

and @ghost

that is the way to go: providing the ISO C API for the standard C/C++ lib and then P/Invoke (FFI) it from .NET RT. This brings advantages on multiple accounts, for example, your lib is consumable from LuaJIT-FFI, node.js, Ruby-FFI or [m]any language runtime; and not limited to .NET.
like you said; to achieve x-platform-ness.
Also, CoreFX is P/Invoking the System.Native libs and it is working out pretty well.

We are building an SDK that calls some OData endpoints and has a bunch of helper functions in .NET Core, but would like to wrap it for other platforms (python, ruby, etc.). I'm am looking for a good approach to this.

Here is my ruby question on stackoverflow: stackoverflow.com/questions/49734820/is-there-a-technique-to-wrap-a-net-core-library-as-a-ruby-gem

Sorry, man! I just saw this today! Did you find a way to do that?

@danfma I have not gotten this working yet. I just picked this back up a few days ago and I've been trying to use this article as a guide, but can't get it to work the same for ruby. https://medium.com/@chyyran/calling-c-natively-from-rust-1f92c506289d

Wondering what is the status. Is there any work in progress? - besides dotnet/coreclr#18013

@gabrielesvelto, the CLI backend branch for GCC is only available in SVN https://gcc.gnu.org/viewcvs/gcc/branches/st/cli-be/, but not in git: https://gcc.gnu.org/git/?p=gcc.git;a=heads. Can it be imported to git with history (so GitHub mirror also picks it up - http://github.com/mirrors/gcc)?

I think the following could tried subsequently:

  • rebase st/cle-be branch against gcc master or gcc-8-branch
  • make the existing pure C implementation to compile both, ijwhost and mscoree compatible binaries
  • add C++ support

@am11 There is an ongoing effort to convert GCC's entire SVN repo to git, so I imagine it will show up eventually.

C++/CLI and similar languages can be implemented without mixed-mode assemblies - i believe it is possible to generate a CLR assembly which DllImports a corresponding native library which contains all native code on load. If it would be done in such manner, it would also be nice to support a toolchain similar to MXE to enable cross-compiling from Linux and macOS - for example, it could be done through an environment variable which points to the MXE root, while MXE provides a C++/CLI compiler (if it is done in GCC manner - needs to be rebuilt to target another platform) and own copies of all libraries/headers used on Windows.

UPD: For a full fledged developer company, a mac mini with jenkins or similar CI software could do the job and compile all needed assemblies without the need to rebuild target-native libraries every time like you would need on travis. Cross-compiling to linux from macOS could be done using crosstool-ng

So nobody's mentioned VS Code or JetBrains Rider?

@HughPH I'd love to see support in Rider, but I think the way forward there is to open a feature request with Jetbrains.

TBH, I'd settle for C++/CLI support in any format!

@HughPH I'm not sure you understand what this issue is about. It's about C++/CLI which is basically .NET and C++ squished together. You can read more about it on Wikipedia or Microsoft Docs.


@cocowalla Cross-platform C++/CLI support does not start with a cross-platform IDE. It is primarily a compiler issue, and a very complex one at that.

It's worth noting that if all you care about is C++/CLI support on Windows, it's coming in .NET Core 3.1:

This support will include projects, IntelliSense, and mixed-mode debugging (IJW) on Windows.

If that's the case, I'd suggest subscribing to the mixed-mode assembly on Windows issue instead of this one.

@PathogenDavid Yes, all I care about is C++/CLI support on Window. I'm also tracking dotnet/coreclr#18013, and got "mixed" (hurhur) up; thought this issue was that one :smile:

@HughPH I'm not sure you understand what this issue is about. It's about C++/CLI which is basically .NET and C++ squished together.

You're right, I didn't understand it to be about C++/CLI. I understood as far as "I want to develop .NET on Linux" - a change of language can make it possible :)

This conversation seems to have been going on for a long time. This is the state of the world:

  • .NET Core is absolutely supported cross-plat and we intend to increase funding for Linux over the next few years.
  • C++/CLI on Windows will be supported, with .NET Core 3.1. We have had many requests for it and are happy to deliver it. It was not a big project, as .NET Core is quite compatible with .NET Framework.
  • C++/CLI on Linux will not be supported and would be very challenging. It would require Microsoft VC++ to support Linux or require Clang or GCC to support C++/CLI. Those are both huge projects with uncertain payoff. It is also unclear if Clang or GCC would ever allow us to upstream our changes. Maintaining an up-to-date fork of a fast moving compiler project forever is very expensive. We have no plans to take on either of those projects.

I understand that cross plat C++/CLI is a huge task, but I'm wondering if there would be any chance documenting the underlying technology required for supporting it? I know the C++/CLI compilers use a lot of tricks and assumptions to implement the bridge (which is why having a C++/CLI compiler on Windows is so important to me, as its currently the only language making these features available to applications). Having those tricks documented (maybe in the docs of the coreclr project) and available for third parties to use as contract this would lower the entry point of actually having a third party C++/CLI (or other language integrating with .NET Core) at _some_ point in time.

I'm personally considering implementing a toy language compiler which can output mixed mode assemblies, so while there may not be cross plat C++/CLI in reach immediately I think being able to output mixed mode assemblies at all could be a first step for having a C++/CLI clang in the future.

@weltkante An old pioneer: https://github.com/tritao/clang-cli

Thanks, I'll definitely have a look at how much of the backend is actually implemented. Most people seem to start by writing a C++/CLI frontend and/or compiling to IL but thats not actually the interesting part to me (both native and IL compilers are well researched), the interesting thing to me is the "ABI" between C++/CLI and .NET because that is the key undocumented element when writing a 3rd party C++/CLI implementation.

ABI between C++/CLI and .NET

It is fairly simple actually:

  • Unmanaged code calling managed code is done via VTableFixups (see section II.25.3.3.3 in ECMA-335). VTableFixups can be used in regular IL-only images too, but no other mainstream .NET language compiler produces them.
  • Managed code calling unmanaged code is done MethodDef RVA field extension: If both MethodImplAttributes.Unmanaged and MethodImplAttributes.Managed bits are set on PInvoke method, the MethodDef RVA is address of the unmanaged method to call.

@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:

  • Decide which part of your bindings make sense to keep as unmanaged C++ and which parts have to be in C#
  • Define "C" interface between the managed and unmanaged parts that will be used with P/Invoke
  • Use custom scripts to generate boiler-plate code and to help you with the refactoring. Keep the scripts simple, handle outliers by hand-written code. This is the part that feels "wrong", but it is surprisingly effective. I have seen several projects do this and it worked reasonably well. The advantage of simple custom scripts is that they give you full control. They do not force you into patterns that are unnatural for your project that is a common problem with interop generator tools (cppsharp, SWIG, SharpGenTools, ...).

I know that this is not the answer you were hoping for, but hope it helps.

Was this page helpful?
0 / 5 - 0 ratings