21

I'm writing a C++ / CLI application, but I want most of the code in my C++ DLL to run natively (i.e. not managed).

I have only got a single CLI class in the module, the other files are all native C++.

So, what is the best way of ensuring that those native classes are run... Well, natively?

Should I:

  • A) Add #pragma unmanaged to the top of every native class
  • B) Just add #pragma unmanaged before the includes in my single CLI class
  • C) Something else?

Thanks

Xenoprimate
  • 7,691
  • 15
  • 58
  • 95

3 Answers3

21

The usual way I do this is to put the native code into a static library project with no .NET support (compile without /clr). You can turn off /clr for individual files in a C++/CLI project but then precompiled headers get really confused. Using a separate library project, it's easy to have a native pch for the native code and a managed pch for the managed code.

Then I link my C++/CLI code with that native C++ .lib to create the DLL. All you do is set a project dependency and Visual Studio takes care of the rest.

You can also use #pragma managed(push, off) and #pragma managed(pop) if you absolutely have to combine native and managed code in the same compilation unit. But usually any code that's in header files is there because you're intending to have it inlined... which means it should be in managed mode when included into a managed CU, so it can be inlined into managed functions.


Despite his comments maligning this answer, Hans has begun recommending my approach.

Community
  • 1
  • 1
Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • 10
    @Hans: From your comment I can only assume you haven't actually taken the approach recommended in your answer. And that you didn't read my answer completely, because I gave that solution as well, and pointed out the problems it causes with precompiled header files. – Ben Voigt Aug 03 '13 at 22:36
  • 1
    I also first tried Hans's approach, but then hit the PCH problem -- I've now split the native stuff into a static lib and it works like a charm. (Also, imho, lots cleaner, as there are no file-specific settings, only project-wide settings.) – Martin Ba Dec 07 '13 at 21:47
  • 2
    `#pragma` tip did the trick in my case. An unmanaged header file inclusion was unavoidable. Wrapping this inclusion with the `#pragma push/pop` was a quick and clean solution for me. – Keugyeol Feb 01 '17 at 02:20
18

You don't have to jump through hoops to ensure this. The compiler will only ever emit IL when it compiles your program with the /clr option turned on. It looks like a project option but it is not.

Just select your .cpp files that contain native code. Select more than one of them by holding down the Ctrl key and clicking the file in the Explorer windows. Right-click + Properties, C/C++, General. Change the "Common Language Runtime Support" setting to "No...".

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • 2
    If you're going to give step-by-step instructions for this, you'd best include turning off usage of precompiled header files for those CUs as well. Because the pch will be created with managed code inside, and the compiler will abort if it is run without `/clr` and sees that pch. – Ben Voigt Aug 03 '13 at 22:37
  • This approach is the simplest, but @BenVoigt was correct. I had to change the precompiled header usage to /Yc instead of /Yu in order to compile. I haven't looked at the result with ildasm yet, though. – Xenoprimate Aug 04 '13 at 14:47
1

Surround #includes of unmanaged code with #pragma managed(push, off) and #pragma managed(pop).

Do not apply to managed code.

Example:

#include "MyManagedClass.h"

#pragma managed(push, off)
#include <string>
#include <vector>
#pragma managed(pop)
Technophile
  • 464
  • 6
  • 9
  • MS Documentation says: ["Add the pragma after #include statements. Don't use it before any #include statements."](https://learn.microsoft.com/en-us/cpp/preprocessor/managed-unmanaged?view=msvc-160) – Keith Russell Oct 22 '21 at 02:13
  • 1
    @KeithRussell I agree that this was in the technical documentation. Unfortunately, it did not work. Don't tell me, tell the compiler... – Technophile Oct 23 '21 at 00:45