C++Cli. Are Native Parts Written in Pure C++ But Compiled in Cli as Fast as Pure Native C++

C++CLI. Are native parts written in pure C++ but compiled in CLI as fast as pure native C++?

In C++/CLI, managed types (ref class for example) and their members are compiled to MSIL. This means no use of SIMD, and much less optimization (at least in the current version of .NET, and the reasons given by Microsoft aren't changing any time soon, although they could change their assessment of the tradeoffs).

Native types, on the other hand, can be compiled either to MSIL or to native machine code. Although Visual C++ doesn't have the best C++ optimizer in the world, it's very very good. So my recommendation would be to compile to native code. Visual C++ will use C++ interop when calling in between managed and native code, which is very efficient (it's the same internalcall technology used for all .NET's built-in functions such as string concatenation).

To make this happen, you can either put your time-critical code in a separate object file (not separate DLL!, let the linker combine managed and unmanaged code together into a "mixed-mode" assembly) compiled without /clr, or bracket it with #pragma managed(push, off) ... #pragma managed(pop). Either way will get you maximum optimizations and allow you to use SIMD intrinsics for very speedy code.

Understanding of Managed C++

It is a big topic with very gritty implementation details. Hard to address them all, but there are some misconceptions in the question. Let's address those, might help to get to next stage.

Moreover, how is it able to use .NET assemblies (which are CIL)?

Not just CIL, the linker produces a mixed-mode assembly. Contains both .NET metadata + msil and native code. In fact, as far as the OS loader is concerned, it is the native code in the executable file that is normal. No different from the kind produced by a native C++ compiler. It gets loaded and relocated just like a pure native executable image. It is the .NET metadata + msil that is the oddball. To the loader it just looks like a chunk of data, it doesn't touch it at all. Only the CLR does.

... use Standard C++ code (which isn't compiled to CIL)

Not quite accurate, native C++ code can be compiled to msil or machine code. What you get depends on whether the /clr compile option was used or the #pragma managed that was in effect at the function level. CIL does not compare that well to, say, the bytecode used in the Java JVM. It is more powerful and can support any C++03 compliant native C++ code. Sometimes you do this on purpose to take advantage of reverse pinvoke (native code calling managed code). Sometimes it is done by accident and entirely too much native C++ code gets compiled to msil. The machine code produced by the jitter is not as optimal (it optimizes under time constraints) and is not managed in any way. It is not verifiable and doesn't get garbage collector love.

Best mental image for CIL is as the Intermediate Representation that is used in any native C++ compiler between the front-end (parser) and the back-end (code-generator and optimizer). Often an invisible implementation detail but gets more visible when you use a C++ compiler that uses LLVM (like Clang does). The .NET just-in-time compiler does at runtime what LLVM does at compile time.


Most programmers have the mental image of a giant mode switch being thrown when managed code calls native code (or the other way around). That is not accurate at all. You might want to take a look at this post, shows the difference between machine code produced by the C++ compiler's back-end and the jitter. Key is it is almost identical, an essential feature to ensure managed code is competitive with native code. Helps to clarify how managed code calling native code, or the other way around, is not that special.

Another misconception is that managed code is automatically safer. Not quite true, a language like C# lets you party with pointers and scribble around on the stack just like you can with C++ and you can corrupt memory just as easily that way. It is just partitioned better, it forces you to be explicit about it with the unsafe keyword. No such constraints on C++/CLI, anything goes.

The essential difference between managed and native code is a data structure that the jitter generates when it compiles msil. Extra data you don't get from a native compiler. That data is required by the garbage collector, it tells it how to find object roots back. More about that data in this post. Having to conform to that data and allowing the GC to get its job done is what makes managed code a bit slower at runtime.

Could C++.Net assemblies be decompiled easily?

There is no "C++.Net". There is C++/CLI, which is a C++-like language that can be used to glue native C++ code with the .NET world. The managed code you write in it (ref classes) will be compiled to MSIL. The "native" code will compile to either MSIL or native. If you want to compile some parts to native code you need

#pragma managed(push, off)

void foo() {}

#pragma managed(pop)

in your source. The managed pragma can be used to choose the compilation target per-function. Or you can compile without the /clr flag per-module and set your project to produce a mixed-mode assembly.

Be aware that marshaling the native types to .NET and back can take a serious performance hit on your application - and that happens every time you cross the native-managed boundary. But interoperation between such embedded native code and managed code is much faster than normal p/invoke.

See also this question: C++CLI. Are native parts written in pure C++ but compiled in CLI as fast as pure native C++?

Will C++/CLI + C++ Native increases performance?

When I link static lib with C++/CLI, will it not become managed code? Means will it not come under CLR.

No, not necessarily. In C++/CLI, all managed types will be compiled to MSIL and the code will run under the CLR. Native types are either compiled to MSIL or native machine code, depending on your compiler options:

  • The /clr option generates a mixture of native and managed code.
  • The /clr:pure option generates a managed-only assembly that can contain native types compiled to MSIL. This works basically like C# code compiled with the /unsafe option.
  • The /clr:safe option generates a managed-only assembly that contains no native code. This works basically like C# code compiled without the /unsafe option.

Does using C++(Native) static lib with C++/CLI in C# increases my performance? Can I not achieve writing code in C# itself rather than native code.

Like all optimization questions, the answer is that it depends. On the one hand, native code is often faster than managed code and can be more highly optimized (e.g. with the use of SIMD). On the other hand, there is a performance hit associated with mixed-mode assemblies. The C++ interop implementation is usually quite fast (certainly much faster than P/Invoke from C#), but if the gains you're getting from compiling to native code are not substantial enough, it may still not be worth it. The only way to really know is to test the two options.

Managed code often gets a bad rap, especially from seasoned C++ programmers, but the truth is that well-written C# code can be just as fast if not faster than the equivalent native C++ code. It's also a lot easier to shoot yourself in the foot in C++, so if you've got a team of developers who are C# experts and not necessarily C++ experts, you're likely to end up with poorly-written and slower C++ code. Finally, when the rest of your project is all in C#, the decreased maintenance costs may mean that even similar performance is acceptable.

Windows Phone 7 and native C++/CLI

c++/cli can theoretically be used with WPF/Silverlight using the trick of replacing the C# generated from the XAML with a macro definition that can be used inside the main class in a code behind file. I worked out this technique but haven't had the motivation to take it beyond theory - I'm quite happy mixing languages.

As far as using c++/cli in a pure safe mode for your logic code, this may still not be possible but I'd love to hear how someone goes trying it now. Whilst researching it for Silverlight back in 2008 I found this daunting silverlight forum comment:

I just gave Silverlight&C++ it a try by compiling the MSIL from my C++ project into a Silverlight-compatible DLL. The good news: it works, and you can call this code from a Silverlight project. The bad news: The C++ compiler apparently uses MSIL instructions that Silverlight disallows.

So, if you try this, even with the simplest of programs, you'll almost immediately get the exception "Operation could destabilize the runtime." To me, this makes it seem less likely that we'll see Silverlight for C++ soon, as the compiler will need to behave quite a bit differently.

C++/CLI application hanging after compiling on Windows 10

This is a generic problem called "LoaderLock". The operating system makes very strong guarantees when it calls the DllMain() entrypoint of a DLL. Strictly in loading order, they never run at the same time. There is a lock in the OS loader that ensures these promises are kept.

And a lock always has the potential to cause deadlock. It will happen when the DllMain() entrypoint does something unwise like loading the DLL itself with LoadLibrary(). Or call a function that requires the OS to have a DLL already loaded. Can't work, its DllMain() entrypoint can't be called because the loader lock is held. The program will freeze. C++/CLI apps are prone to this problem, lots of stuff tends to happen in DllMain(). Indirectly, you can't see it in your code.

You can only see it with the debugger. You must change its flavor, Project > Properties > Debugging > Debugger Type, change it from "Auto" to "Mixed". You'll now also see the unmanaged code that is running including the OS loader functions, name starts with "Ldr". Be sure to enable the Microsoft Symbol Server with Tools > Options > Debugging > Symbols. And be sure to use the Debug > Windows > Threads debugging window as well, the truly tricky loader deadlocks that don't repeat well or appear to be affected by the OS version are caused by another thread loading a DLL.

Diagnosing and fixing it can be difficult, be sure to reserve the time you need to dig in. If you can't make heads or tails of the stack traces then post them in your question.

What are the situations or pros and cons to use of C++/CLI over C#

With C++/CLI you can create, broadly speaking, three types of objects:

  1. Managed types. These will compile down to essentially the same IL as the equivalent C#. There is no performance opportunity here.
  2. Native types. Compiles down to native code as if you'd used straight C++.
  3. Mixed mode types. These compile down to managed code, but allow you to refer to native types too.

You might think of (3) as being like writing C# code with PInvoke code to accessing the native stuff - except all the PInvoke stuff is generated for you.

There's more to it than that, of course, as well as some caveats - but that should give you an idea of how it's useful.

In other words it's really a glue language. While you can write fully fledged apps in C++/CLI it's more normal to keep the managed and native parts separate and use C++/CLI to bridge the two more cleanly than with PInvoke.

Another common use is to extend and existing, native, C++ code base with .Net library calls.

Just be careful that you partition your code well as it can be quite subtle sometimes in compiling your pure C++ code down to IL transparently!

As to your sidenote: PInvoke is a particular type of Interop. Interop comes in other forms too, such as COM Interop. In fact, more accurately, PInvoke is a set of language features that make Interop with native code easier.



Related Topics



Leave a reply



Submit