An Update on C++/CLI and .NET Core

Will Buik

The first public release of our C++/CLI support for .NET Core 3.1 is now available for public preview! It is included in Visual Studio 2019 update 16.4 Preview 2. We would love it if you could try it out and send us any feedback you have. For more info about what this is and the roadmap going forward, check out my last post on the future of C++/CLI and .NET Core.

To get started make sure you have all the necessary components installed. C++/CLI support for desktop development is an optional component, so you will need to select it on the installer’s right pane:

Install the “Desktop development with C++” workload and be sure to include the optional “C++/CLI support” component.

You will also need the .NET Core cross-platform development workload. It installs everything you need including the .NET Core 3.1 SDK:

Alt: Install the “.NET Core cross-platform development” workload.

Creating a C++/CLI .NET Core Project

First, you will want to create a “CLR Class Library (.NET Core)” or “CLR Empty Project (.NET Code)”. The Class library template includes some additional boiler plate to set up an example class and precompiled header that may make it easier to get started. The empty project is ideal for bringing in existing C++/CLI code. Retargeting existing C++/CLI projects to .NET Core isn’t recommended.

There isn’t currently a template for C++/CLI console or Windows applications that can be used with .NET Core. Instead you must put application entry point outside of the C++/CLI code. In general, we strongly recommend keeping the C++/CLI projects as narrow in scope as possible to handle just the interoperability between .NET Core and other C++ code.

Once you create one of these projects, you can reference it from other .NET Core projects like any other class library – with one important caveat. .NET Core projects are typically architecture agnostic. You see this as the architecture “Any CPU” in the Configuration Manager and “MSIL” in the build logs. This is the default for all .NET Core projects. If you reference any C++/CLI class libraries, you must specify an explicit architecture for the non-C++ projects instead of “Any CPU”.

You can set a project’s architecture by using the Configuration Manager.

If the architectures don’t match, you will see this warning and attempting to load the C++/CLI class library will fail at runtime:

“Warning MSB3270 There was a mismatch between the processor architecture of the project being built "MSIL" and the processor architecture of the reference…”

To resolve this, make sure all projects in the solution are using the same architecture of “x86” and “Win32” or “x64”. If you are using ASP.NET Core, there is an additional consideration. Your projects also need to match the architecture of IIS Express. This is typically “x64”. If you see a “500 server error” due to the loader failing, this may be what the problem is.

Send us Feedback

Please try this out. We’d love to hear your feedback to help us prioritize and build the right features. We can be reached via the comments below or email (visualcpp@microsoft.com). You also can always send us general feedback via Developer Community.

28 comments

Discussion is closed. Login to edit/delete existing comments.

  • Michael Martell 0

    I am using the new .NET Core support for C++/CLI in an Apache project. Using Microsoft Visual Studio Professional 2019 Preview
    Version 16.5.0 Preview 1.0.

    I’m getting an EETypeLoadException. Any assistance would be greatly appreciated.

    When I enable loading of system symbols, I get prompted for location of: f:\workspace\_work\1\s\src\jit\lclvars.cpp

    So the EETypeLoadException is thrown in clrjit.dll, from lclvars.cpp

    Here’s the exact exeption and call stack:

    Exception thrown at 0x00007FFC0BFB9129 in PutGetRemoveCore.exe: Microsoft C++ exception: EETypeLoadException at memory location 0x0000004066178CF0. occurred

    Call stack is:

    [External Code]
    clrjit.dll!Compiler::lvaInitTypeRef() Line 275 C++
    clrjit.dll!Compiler::compCompileHelper(CORINFO_MODULE_STRUCT_ * classPtr, ICorJitInfo * compHnd, CORINFO_METHOD_INFO * methodInfo, void * * methodCodePtr, unsigned long * methodCodeSize, JitFlags * compileFlags, CorInfoInstantiationVerification) Line 5871 C++
    clrjit.dll!Compiler::compCompile(CORINFO_METHOD_STRUCT_ * methodHnd, CORINFO_MODULE_STRUCT_ * classPtr, ICorJitInfo * compHnd, CORINFO_METHOD_INFO * methodInfo, void * * methodCodePtr, unsigned long * methodCodeSize, JitFlags * compileFlags) Line 5367 C++
    clrjit.dll!jitNativeCode(CORINFO_METHOD_STRUCT_ * methodHnd, CORINFO_MODULE_STRUCT_ * classPtr, ICorJitInfo * compHnd, CORINFO_METHOD_INFO * methodInfo, void * * methodCodePtr, unsigned long * methodCodeSize, JitFlags * compileFlags, void * inlineInfoPtr) Line 6663 C++
    clrjit.dll!CILJit::compileMethod(ICorJitInfo * compHnd, CORINFO_METHOD_INFO * methodInfo, unsigned int flags, unsigned char * * entryAddress, unsigned long * nativeSizeOfCode) Line 319 C++
    hostpolicy.dll!coreclr_t::execute_assembly(int argc, const char * * argv, const char * managed_assembly_path, unsigned int * exit_code) Line 152 C++
    hostpolicy.dll!run_app_for_context(const hostpolicy_context_t & context, int argc, const wchar_t * * argv) Line 247 C++
    hostpolicy.dll!run_app(const int argc, const wchar_t * * argv) Line 276 C++
    hostpolicy.dll!corehost_main(const int argc, const wchar_t * * argv) Line 390 C++
    hostfxr.dll!execute_app(const std::wstring & impl_dll_dir, corehost_init_t * init, const int argc, const wchar_t * * argv) Line 146 C++
    hostfxr.dll!`anonymous namespace’::read_config_and_execute(const std::wstring & host_command, const host_startup_info_t & host_info, const std::wstring & app_candidate, const std::unordered_map<enum known_options,std::vector<std::wstring,std::allocator>,known_options_hash,std::equal_to,std::allocator<std::pair<enum known_options const ,std::vector<std::wstring,std::allocator>>>> & opts, int new_argc, const wchar_t * * new_argv, host_mode_t mode, wchar_t * out_buffer, int buffer_size, int * required_buffer_size) Line 502 C++
    hostfxr.dll!fx_muxer_t::handle_exec_host_command(const std::wstring & host_command, const host_startup_info_t & host_info, const std::wstring & app_candidate, const std::unordered_map<enum known_options,std::vector<std::wstring,std::allocator>,known_options_hash,std::equal_to,std::allocator<std::pair<enum known_options const ,std::vector<std::wstring,std::allocator>>>> & opts, int argc, const wchar_t * * argv, int argoff, host_mode_t mode, wchar_t * result_buffer, int buffer_size, int * required_buffer_size) Line 952 C++
    hostfxr.dll!fx_muxer_t::execute(const std::wstring host_command, const int argc, const wchar_t * * argv, const host_startup_info_t & host_info, wchar_t * result_buffer, int buffer_size, int * required_buffer_size) Line 541 C++
    hostfxr.dll!hostfxr_main_startupinfo(const int argc, const wchar_t * * argv, const wchar_t * host_path, const wchar_t * dotnet_root, const wchar_t * app_path) Line 33 C++
    PutGetRemoveCore.exe!exe_start(const int argc, const wchar_t * * argv) Line 220 C++
    PutGetRemoveCore.exe!wmain(const int argc, const wchar_t * * argv) Line 279 C++
    [External Code]

    • Michael Martell 0

      From what I’ve read, Mixed Mode assemblies are supported, but an additional piece of info I forgot to mention is that our C++/CLI assembly links statically to our native C++ library. Could that be part of the problem. I will try a dynamic link and report back.

      • Michael Martell 0

        Not a mixed mode assembly problem. My mixed mode dll is now being loaded, but I’m getting a TypeLoadException when my sample app calls C++/CLI functions that return generic types:

        System.TypeLoadException
        HResult=0x80131522
        Message=Method implementation on an interface ‘Apache.Geode.Client.IRegion`2’ from assembly ‘Apache.Geode.Core, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null’ must be a final method.
        Source=
        StackTrace:

        So far I’m unable to find anything about “must be a final method”. Looks like the error maps to: IDS_CLASSLOAD_MI_FINAL_IMPL in the dotnet CLR source.

  • Morten Nielsen 0

    What about ARM64 support?

    If I try I’m told this is missing: “msvcmrtd_netcore.lib” when compiling. I see this lib is provided for ARM32, x64 and x86, but ARM64 appears to be missing. Oddly enough there are other ARM64 netcore native libs.

  • XZiar 0

    I just upgrade to VS16.4 and try to migrate my project.
    But I can’t find any “Framework” for target .net core 3.1 when I try to add reference of WPF.
    I need it to convert my custom structure to WPF’s structure like System::Windows::Media::Color…

    • Hiroyuki Yamada 0

      I have the same trouble as you had.
      I want to use System.Windows.Threading.Dispatcher.
      But I can’t find any Framework to add reference.

    • Benjamin 0

      I have the same issue. Not able to write Wpf controls in cli/c++ for best support of native c++ libraries.

  • Peter Beck 0

    I am currently trying to migrate a Windows project to NetCore 3.1.
    It is an MFC application that calls modules in a C # library through a CLR wrapper.

    [App.exe (C ++)] —> [CRL Wrapper (C ++ / CLI)] —> [.NET Core 3.1 Library (C #)]

    So far, I have not been able to get even a small test application to work. Everything is ok for the compiler. But instantiating the wrapper class in the application produces the following exception:

    Unhandled exception at 0x770035D2 in MFCApplication.exe:
    Microsoft C ++ exception: long at memory location 0x0059FB5C. occurred

    stack:
    [External code]
    Ijwhost.dll! Start_runtime_and_get_target_address (unsigned int cookie) Line 145 C ++
    Ijwhost.dll!_start_runtime_thunk_stub@0 () Line 37 Unknown
    MFCApplication.exe! CMFCApplicationApp :: InitInstance () Line 58 C ++
    [External code]
    MFCApplication.exe! WWinMain (HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, wchar_t * lpCmdLine, int nCmdShow) Line 26 C ++
    [External code]

    Is this scenario currently possible with NetCore 3.1?
    I use VS 2019 (16.4.1)

  • Sohno Mehar 0

    The @HostListener decorator is used to set up an event binding on the host element and is applied to a method. The example directive relies on the browser’s DOM API to manipulate its host element, both to add and remove class memberships and to receive the click event. Working with the DOM API in an Angular application is a useful technique, but it does mean that your directive can be used only in applications that are run in a web browser….. Read More

  • Érico P 0

    Please, write a bit on how to workout a project that has C++ CLI that needs to be cross Platform. Essentially, paths to proceed, since it seems it won’t be cross platform.

  • Philipp Sonntag 0

    When I’m trying to create a basic dll from the template without any modifications, Visual Studio shows me an exception at the start of every file, that System::String is not found, but the Core CLR is supported. (” Common Language RunTime is supported in file but ‘System::String’ type was not found “).

    Has anyone had this issue before, or am I just missing some includes or something?

Feedback usabilla icon