C++ mixed mode applications
While calling native code from CLR code is reported everywhere as one of the key benefits of .NET technology, the other way around (that is, calling CLR code from native) is often considered an useless addition, if one knows at all of its existence.
Actually this is, instead, the reason I find .NET so exciting to work with. The ways this capability can be used are actually only limited by one’s imagination.
So let’s start our experiment.
Note : the following procedure should work with Visual C++.NET 2002 and 2003. With Visual C++.NET 2005 you should at least change the “/clr” flag to “/clr:oldSyntax”. Look at this MSDN entry to see a list of breaking changes in Visual C++ 2005 compiler.
First step : project creation
Let’s start with a practical example. The first step is creating a simple Win32 project. We want less junk around as possible, so we’ll choose a VisualC++ project / Win32 project / Windows application.
After the creation, open the resource file and add a menu entry, with some string you want and id ID_FILE_MSGBOX . Then open our main cpp file, and in the window procedure (WndProc function) let’s add a case handling the ID_FILE_MSGBOX menu entry and calling a CallDotNetMessageBox() function. Also we add the typical extern void CallDotNetMessageBox(); prototype at the beginning of our file.
Second step : adding managed C++ code
After this we create our simple and basic managed C++ file. The file contents will be :
#using "mscorlib.dll"
#using "system.Windows.Forms.dll"
void CallDotNetMessageBox()
{
System::Windows::Forms::MessageBox::Show("Hello from .NET world!");
}
Third step : fixing compiler options
If you tried to build the project, you would have noticed that nothing was working. So here are the steps required :
In Project Properties :
- Debugging, Debugger type : you should select “Mixed” because Auto doesn’t work 100% of the times ![]()
- C/C++, General Debug Information Format : you should not use “Program Database for Edit & Continue” here, so change it in “Program Database (/Zi)
- C/C++, Code Generation, Runtime Library : by using a CLR source, your program is automatically multithreaded, so you should change your runtime library to a multithreaded one.
- C/C++, Precompiled Headers : while it’s possible to use precompiled headers in mixed mode executable, they should be handed special care. Also I usually disable them anyway in every project, so let’s disable them now
In the properties of the file containing managed C++ code :
- C/C++, General, Compile as managed : Assembly support (if you are using Visual C++ 2005, add “/clr:oldSyntax” manually)
- C/C++, Code Generation, Basic Runtime Checks : set to default
- C/C++, Code Generation, Enable Minimal Rebuild : No
Fourth Step : Build & Run !
You’re done, you should just build, run and test the example.
You will notice that the very first time you click on your menu entry, it will take some seconds before the messagebox appears. Then, after that, it will appear almost instantly. This is because the first time the CallDotNetMessageBox() function is called, it is not yet converted in native code and it’s still in CLR format. So the very first time the JIT compiler starts compiling the code and you have that long delay. After that the code is much more responsive and, for some but not all the purposes, the delay is no more noticeable. Also note that the code is very much more responsive if you run it outside the debugger, so don’t panic when you see such long frozen times during debug
Here you can find the sample sources (VC2002) : Source files
