dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
14.85k stars 4.62k forks source link

Support mixed-mode assemblies on Windows #10333

Closed morganbr closed 4 years ago

morganbr commented 6 years ago

This issue will track progress toward supporting loading and running mixed-mode assemblies on CoreCLR. The main goal is to provide support for WPF and other existing C++/CLI code on .NET Core. Some of the work will be dependent on updates to the MSVC compiler.

Steps include:

This is related to dotnet/runtime#4116, but cross-platform support is outside of the scope of this issue as it's a compiler feature, not a runtime feature.

rickbrew commented 6 years ago

Paint.NET author here ... you've got my attention :D I have 50 KLOCs of C++/CLI code ... let me know if you need a guinea pig :)

morganbr commented 6 years ago

Thanks, @rickbrew. It'll be a while until we're ready for Paint.NET, but we'll keep you in mind.

mjsabby commented 6 years ago

I think we can start by reverting https://github.com/dotnet/coreclr/commit/1aa7d6b8796f7e28a63162117c5bb16a207a472b to at least allow the ability to load multi module assemblies.

morganbr commented 6 years ago

@mjsabby, multi-module assemblies are orthogonal to mixed-mode. (Multi-module means you linked together netmodules using alink.exe, mixed mode means you have a combination of managed and native code in the same assembly). If you have a requirement for multi-module assemblies, I'd suggest filing a separate issue outlining what you need.

mjsabby commented 6 years ago

@morganbr Thanks. I'm not sure why I concluded that C++/CLI needs netmodule support.

pongba commented 5 years ago

Awesome we're making progress on this ground. C++/CLI is what we use to bridge native service to the awesome .NET world. So far no other alternative achieves the elegance of C++/CLI as a glue language so it's fair to say that we're going to rely on C++/CLI as an integral part of our service.

Some time ago in the spirit of searching for performance gains by migrating from .NET framework to .NET core I sadly found that .NETCore doesn't go together with C++/CLI (even though we don't care about cross-platform yet).

And now this thread lifts my mood đź‘Ť Looking forward to the release (as while I searched for solutions I saw a lot of people had the same need with C++/CLI in their own projects)

nietras commented 5 years ago

@morganbr given that "Loading mixed-mode assemblies into running managed code" is done, should it be possible to use latest .NET Core 3.0 preview together with mixed mode assemblies on Windows? E.g. from a C# application?

We intent to use .NET Core 3.0 with WPF and have quite a lot of C++/CLI dependencies/libraries (a lot third party too), so looking forward to this.

morganbr commented 5 years ago

@nietras, I'm glad to hear you're eager to give this a shot. It's probably a little early to try it with the latest preview though. While the runtime can run mixed-mode assemblies now, the C++ compiler also needs some changes to make everything work smoothly.

In case anyone's interested in details, the main C++ compiler changes are:

  1. Be able to build against .NET Core assemblies instead of .NET Framework (this isn't strictly blocking, but can cause issues if the assembly references a type that isn't in Core or wants to use a type that isn't' in Framework)
  2. An assembly built with the current release of the C++ compiler will load and call into mscoree.dll on startup, which starts up .NET Framework. As you might imagine, having both runtimes think they loaded the assembly can cause lots of problems.
pongba commented 5 years ago

@morganbr will the changes to C++(CLI) compiler that supports .NETCore be released together with the next version of Visual Studio, or will it be released out-of-band?

morganbr commented 5 years ago

@pongba, I don't think we're ready to say exactly when or how we'll first distribute that version of the compiler, but it will eventually get distributed with Visual Studio.

batzen commented 5 years ago

So should it be possible to load assemblies which have ddlexports (vtfixup etc.) in them with the current preview of .net core 3.0? I am asking this because i just get a BadImageFormat exception when trying to load such assembly which i compiled with .net core 3.0 and used ildasm and ilasm to add the exports. The same code works when compiling with .net 4.6.2. I can provide the il code if required as a repro.

Berrysoft commented 5 years ago

Considering of C++/WinRT, is it possible to write a standard C++ projection for .NET Core?

batzen commented 5 years ago

@morganbr Would be nice to get a response from you. Not being able to at least load assemblies which contain an dll export prevents me from porting https://github.com/cplotts/snoopwpf to .NET core 3.0.

morganbr commented 5 years ago

@batzen, you could be hitting a few different issues. You might be able to narrow them a bit by seeing if directly calling LoadLibrary on your assembly in the .NET Core process works. Some possible issues:

  1. Processor architecture mismatch (in particular, .NET Core is x64 by default while .NET Framework is x86 by default)
  2. Depending on how exactly your imports/exports are set up, your assembly might be causing mscoree.dll to load. If that happens, it tries to start .NET Framework and all kinds of bad things (including BadImageFormat) can happen. You should be able to spot mscoree.dll loading in a debugger if you have mixed-mode debugging enabled.
  3. Something specific to your ildasm/ilasm process. You'd need to debug further into the error to find out if there's something .NET Framework-specific that you're relying on.
morganbr commented 5 years ago

@Berrysoft, .NET Core supports WinRT, although some of the features may only be available in UWP applications.

Berrysoft commented 5 years ago

@morganbr Oh, no, I mean, the current grammar of C++/CLI is non-standard. It is possible to make a projection of .NET Core with standard C++ grammar, so that other standard C++ compilers will compile the code, just like what C++/WinRT did for WinRT?

batzen commented 5 years ago

@morganbr

  1. Architecture is ok. Tried both, x86 and x64.
  2. It's a pure .net core 3.0 assembly. No reference to mscoree. Just one method in one class. IL code can be found at https://gist.github.com/batzen/8b1ed3e7269b4aaaacee846f188ef347
  3. I just run ilasm ManagedCore.il /outfile=ManagedCoreExported.dll /dll on the IL code from the gist.

Doing exactly the same for the equivalent IL code for .NET framework, which then of course contains mscoree references, works without an BadImageFormatException. Loading of the modified assembly is done via Assembly.LoadFile.

If mixed mode assembly loading is supported in .NET core 3.0 are there any samples available? Some UnitTests you can point me to?

batzen commented 5 years ago

As this issue is assigned now, i guess you were able to reproduce it?

AaronRobinsonMSFT commented 5 years ago

@batzen Mixed mode assemblies aren't supported in .NET Core 3.0 yet. This issue is tracking that support. @jkoritzinsky is actively working on investigating what needs to happen and the changes that will need to be introduced. Look for a design doc on this in the next week or two.

batzen commented 5 years ago

@AaronRobinsonMSFT if loading mixed mode assemblies not currently not support the task point "Loading mixed-mode assemblies into running managed code" in this issue should be unchecked, shouldn't it?

jkoritzinsky commented 5 years ago

@batzen We support loading mixed-mode assemblies into running managed code with some specific workarounds to avoid accidentally loading .NET Framework into the process. The runtime work is already complete for that feature.

We're still working on starting the runtime when a mixed-mode assembly is loaded from native code instead of managed code and starting the runtime if needed. Additionally, there's some compiler work needed to have the Visual C++ compiler link against something other than .NET Framework's mscoree.dll for loading the runtime.

Support for setting up the vtfixup table in a non-mixed mode assembly is something else that I think is the base problem of your isssue.

ovebastiansen commented 5 years ago

Is there a sample somewhere on how to set up a mixed mode assembly for dotnet core 3.0 and how to load that into a running managed application?

//Ove

On my phone


From: Jeremy Koritzinsky notifications@github.com Sent: Monday, February 4, 2019 22:38 To: dotnet/coreclr Cc: ovebastiansen; Manual Subject: Re: [dotnet/coreclr] Support mixed-mode assemblies (#18013)

@batzenhttps://eur04.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fbatzen&data=02%7C01%7C%7C014210d3b7f34fdd9b3e08d68ae91c40%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C636849131130015110&sdata=lF30W2mA8AdheQqc30GIRdf5uAxNX%2B0wBN5gLX33ZaQ%3D&reserved=0 We support loading mixed-mode assemblies into running managed code with some specific workarounds to avoid accidentally loading .NET Framework into the process. The runtime work is already complete for that feature.

We're still working on starting the runtime when a mixed-mode assembly is loaded from native code instead of managed code and starting the runtime if needed. Additionally, there's some compiler work needed to have the Visual C++ compiler link against something other than .NET Framework's mscoree.dll for loading the runtime.

Support for setting up the vtfixup table in a non-mixed mode assembly is something else that I think is the base problem of your isssue.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHubhttps://eur04.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fdotnet%2Fcoreclr%2Fissues%2F18013%23issuecomment-460422911&data=02%7C01%7C%7C014210d3b7f34fdd9b3e08d68ae91c40%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C636849131130025114&sdata=hpgDfah2UN5vjCgi84BWB7BhxqggitHhvwB78%2Bnl%2FQM%3D&reserved=0, or mute the threadhttps://eur04.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fnotifications%2Funsubscribe-auth%2FAQSuAeLAM3EyGvUwgCMu8BnkzuyhtDTFks5vKKhXgaJpZM4UAdnr&data=02%7C01%7C%7C014210d3b7f34fdd9b3e08d68ae91c40%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C636849131130025114&sdata=gcW6PgaOqzl6NVHQLRFP51azZHHDiQ6Y0igINNmbrFk%3D&reserved=0.

meirkr commented 5 years ago

Hi. Any progress with the ability to create c++/cli assembly and load it into my .Net core app? Is it planned for. Net core 3.0 release?

AaronRobinsonMSFT commented 5 years ago

@meirkr There is good progress. See https://github.com/dotnet/coreclr/pull/22636 and https://github.com/dotnet/core-setup/pull/5185. Much of what we are waiting on is VC++ tooling support. The plan is for the .NET Core 3.0 release.

jkoritzinsky commented 5 years ago

The runtime/hosting work for C++/CLI has been merged in. We're just waiting on the VC++ compiler/tooling support now before we can validate the end-to-end experience.

fabricefou commented 5 years ago

@jkoritzinsky, will the new VC++ compiler targeting .Net core be able to compile old c++ runtime (vc10 for example) ? Thanks

ghbeta commented 5 years ago

hope we can test this with preview 4

weltkante commented 5 years ago

@ghbeta we are already at VS 16.0 preview 5 ... so I don't know what you mean with preview 4 ;-)

From what it looks like you probably can expect something for VS 16.1 preview 2, at least the comment in the WPF repository indicates thats their current plan (which of course could change if things go badly, so don't take it as officially announced)

jkoritzinsky commented 5 years ago

@fabricefou I am not sure if it will be able to target old runtimes. I don't believe it will be able to target anything lower than the VS2019 MSVC++ compiler can currently target.

meirkr commented 5 years ago

1. How can it be tracked? Is there a target date already?

2. Is there a temporary workaroind to configure something manually? I guess this activity here have used some solution to develop and test this capability. Haven't it?

ghbeta commented 5 years ago

@ghbeta we are already at VS 16.0 preview 5 ... so I don't know what you mean with preview 4 ;-)

From what it looks like you probably can expect something for VS 16.1 preview 2, at least the comment in the WPF repository indicates thats their current plan (which of course could change if things go badly, so don't take it as officially announced)

i was meant .net core preview 4. just noticed the vs16.1 preview 1 is arrived, hope the c++ compiler will be ready at preview 2, i assume we have to retarget the framework of cli c++ project to .net core 3.0?

gpetrou commented 5 years ago

Will we also be able to share a C++\CLI dll between .NET Core and Framework? We would like to avoid producing two dlls, one for each case. Is there a recommended way to do that?

AaronRobinsonMSFT commented 5 years ago

@gpetrou Unfortunately it is unlikely that will be possible. C++/CLI binaries targeting .NET Framework will have mscoree.dll as the embedded host entry point. For .NET Core, a different host binary will be used - ijwhost.

gpetrou commented 5 years ago

Thanks for the quick reply. If we do have to produce two C++/CLI dlls, can we at least avoid producing two dlls that reference them? We would like to use a .NET Standard dll that references the C++/CLI dll (only on Windows). This .NET Standard dll in turn, can be referenced by other .NET Core or .NET Framework assemblies. So, can we somehow inside the .NET Standard dll decide which C++/CLI dll we need to load?

MathiasMagnus commented 5 years ago

@morganbr @Berrysoft I too would favor an ISO C++ language projection to use on Linux machines with either Clang or GCC and on Windows with Clang or MSVC. Wrapping native libraries for speed and wrap them with .Net goodness would rock. I typically run HPC code but there are times I'd wrap them with .Net and use some other language to call them for convenience. C++/CLI is a nice gluing material, but it's not portable and ISO C++ is moving rapidly, so the extensions are starting to show age.

weltkante commented 5 years ago

What's the status on using C++/CLI? 16.1 preview 2 went live and apparently WPF is now using the new compiler in dotnet/wpf#640, but nothing was in the release notes explaining how to use it yourself.

I'd like experimenting with C++/CLI in .NET Core, what do I have to do to enable it?

svick commented 5 years ago

@weltkante

I believe the most recent information is in https://github.com/dotnet/wpf/issues/607:

Many of you are probably aware that there is currently no support for building C++/CLI in .NET Core. In Dev16.0 (aka Visual Studio 2019), the C++ team has added limited capability (note: I didn’t write “support”) for compiling C++/CLI assemblies targeting .NET Core. For more details on how this works in the WPF codebase, please dig into Wpf.Cpp.props/Wpf.Cpp.targets and search for /clr:netcore. (If you try to use this today, it will probably not work for you due to a bug – please wait until Visual Studio 2019 Preview 2 comes out).

This limited support for C++/CLI has no SDK support yet. In other words, we couldn’t just take a C++/CLI vcxproj project that targeted .NET Framework and retarget it to .NET Core – the underlying NuGet support for discovering .NET Core references and a myriad of other build targets just didn’t exist. We worked with several colleagues in the .NET and C++ teams to build our own limited support for discovering the right NuGet references during build (see CppCliHelper in Wpf.Cpp.targets)

As you noted, VS 16.1 preview 2 is now out, so presumably that bug should now be fixed.

davidhunter22 commented 5 years ago

I'm a bit confused as to where this is all heading. Currently in VS 16.1 Preview 3.0 I create a C++ project. I can then switch on /clr in the properties and select a .NET target framework say v4.7. These are "old" style names like "v4.7" not new SDK ones like "net47". At some point will I be able to type "netcoreapp3.0" and things will just work? If so will the .vcxproj file remain roughly the same as now or will it change to "SDK" style?

weltkante commented 5 years ago

You can set the /clr to netcore already, but be aware that its very early preview, the WPF repository is configuring the project in props/targets files and applying various other configurations because there is no .NET Core project template for C++/CLI yet so everything needs to be set explicitely. I didn't have the time to get it running myself yet, but it looks like everything is there if you want to try for yourself.

I don't think the project format will change to "SDK" style, from looking at the modifications it can all be done in the existing project system.

meirkr commented 5 years ago

I don't understand how shall I try it. This is the current command line generated by the CLR class library template. How to configure it to point to .net core/standard instead of 4.7.2?

/Yu"pch.h" /GS /analyze- /W3 /Zc:wchar_t /Zi /Od /Fd"Debug\vc142.pdb" /Zc:inline /fp:precise /D "WIN32" /D "_DEBUG" /D "_WINDLL" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /Oy- /clr /FU"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.7.2\mscorlib.dll" /FU"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.7.2\System.Data.dll" /FU"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.7.2\System.dll" /FU"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.7.2\System.Xml.dll" /MDd /FC /Fa"Debug\" /EHa /nologo /Fo"Debug\" /Fp"Debug\CoreClrCpp.pch" /diagnostics:column

weltkante commented 5 years ago

@meirkr It doesn't work out of the box yet, it requires a lot of workarounds (that's probably why they didn't even bother to mention it in the VS preview notes that its possible to use C++/CLI). If you know how to read the props/targets of a vcxproj you can look at the WPF project (link in my other answer above) to see what workarounds are needed. Otherwise it's probably best to wait until they can finish proper integration into VS without tons of workarounds.

meirkr commented 5 years ago

can you share an empty project file which has that tweek? It could be a reference to a project file.

weltkante commented 5 years ago

@meirkr sorry no, as said above I didn't have time to get it running myself yet

Also its not just a simple tweak either, for example the build has to configure the C/C++ runtime and also resolve (or hardcode) all managed assembly references manually, which is quite a big workaround to implement. The WPF project file creates a dummy project and parses the results to resolve packages. (I'd probably just hardcode the references for now though, if I were to experiment with it)

Either way, I don't think you can use this by simply tweaking the project file itself yet, you need to have these workarounds which run during the build process. So if you don't understand how it works its probably too early to try it out. (I do understand most of the props/targets used in the linked files but currently don't have the time to reimplement all the workarounds in a standalone project. If I find the time to set up a sample project before VS gets proper integration I'll drop a note here.)

jcapellman commented 5 years ago

Hitting this myself porting a 4.7.1 WPF app to .NET Core 3 - very much looking forward to this working out of the box (even if there are quirks).

jkoritzinsky commented 5 years ago

Update: The feature work on the .NET runtime side is complete. I've marked the issue as blocked as the full scenario isn't yet complete due to the work on the C++ side still being in-progress.

jcapellman commented 5 years ago

@jkoritzinsky Thanks for the update - I guess I will hold off the .NET Core 3 porting effort.

GeorgeS2019 commented 5 years ago

@jkoritzinsky please provide if there is a plan to support mixed-mode assemblies in both Windows and Linux environment under .NET Core 3. Which issues we can follow the progress

weltkante commented 5 years ago

@GeorgeS2019 As far as I know there are no plans for mixed mode assemblies on Linux, there exists no working language equivalent to C++/CLI on Linux so there is not much point in providing the mixed mode capabilities. The current efforts are purely for getting certain Windows interop scenarios running when porting from Desktop Framework to .NET Core. I think you are supposed to use P/Invoke & co if you develop new code and need to interact with native code on Linux.

There are no issues known to me for following Linux mixed mode progress because nothing is planned (i.e. there will be no progress). If you are interested in C++/CLI specifically there is dotnet/runtime#4116 still open but without external contributions probably not going anywhere anytime soon.

SwooshyCueb commented 5 years ago

@weltkante C++/CLI compiled on Windows for .NET works on Mono just fine, even on Linux, provided you use /clr:safe: https://www.mono-project.com/docs/about-mono/languages/cplusplus/

Not sure if this is what you meant by "working language equivalent" but it seems worth mentioning.

weltkante commented 5 years ago

@SwooshyCueb The question was explicitely about mixed mode assemblies (not C++/CLI compiling to managed IL). To produce mixed mode assemblies you currently need a C++/CLI compiler, as there are no other languages producing mixed mode assemblies. Sure, you can configure C++/CLI to compile its input down to IL not containing native code, but then you didn't produce a mixed mode assembly in the first place.