Adding Managed Extension Support
As you can see from the preceding examples, using managed types within C++ is quite easy. Managed types look, taste, and feel very like normal C++ types. However, they're a lot less hassle to use.Building managed C++ assemblies from scratch is a breeze using the Visual C++ project wizards. However, sometimes you might need to add managed C++ support to your existing C++ applications. Let's look at how you go about converting a normal C++ application to a managed C++ application.First, you modify the project settings. Standard C++ applications don't have the correct compiler and linker settings to compile down to the common language runtime. You must add the /clr option, which enables support for Managed Extensions and forces a link to the proper library. To modify the project settings, right-click on the project node in Solution Explorer and choose Properties. Click on the C/C++ folder in the left pane of the Property Pages dialog box. Then click on the General folder under C/C++. Set the Compile As Managed property to Assembly Support (/clr). If your application is an MFC application, you might need to tweak some of the other options, such as turning off the Program Database For Edit & Continue option (/ZI).By default, the /clr compiler option is not in effect. When it is switched on, metadata is generated for all code (wow!). Any code that can be compiled to managed code will be. Naturally, some C++ constructs can be compiled to managed code. The following kinds of unmanaged code will be generated automatically:
__asm blocks.
Functions that use any form of variant args in their parameter list.
Compiler-generated thunks or helper functions. Native thunks are generated for any function call through a function pointer, including virtual function calls.
Functions that call setjmp.
Functions that directly manipulate machine resources. For example, __enable/__disable and _ReturnAddress/_AddressOfReturnAddress cause a function to be compiled as unmanaged native code.
Code that appears after a #pragma unmanaged directive.
Functions that reference aligned types (types declared using __declspec(align(...))
Using the /clr compiler option requires that the /MT compiler option be enabled. This causes the compiler and linker to use the multi-threaded versions of the CRT runtime functions. This is necessary because the common language runtime garbage-collects and calls object finalizers on a thread that runs independently from the main execution thread.Once the target application has been built with Managed Extensions support, you can access all .NET Framework features, including your own managed types and the .NET common library. Notice that the example code for this chapter uses predefined system types (such as String, ArrayList, and Console) as well as types defined within a custom assembly.Of course, there are some caveats about using managed types with unmanaged types. You are forbidden to nest managed types within unmanaged types. This makes sense—how should the destructor of a class holding a managed type behave? You cannot derive a managed type from an unmanaged type—a class has to be managed from the beginning. This means that it's generally impractical to use the Managed Extensions from within an MFC application. You cannot keep a managed type as a member variable for a class. However, you can create an instance of a managed type for the duration of a method call. For example, the following line creates a managed ArrayList within some unmanaged code:
void UseAManagedType() {
ArrayList* al;
al = new ArrayList();
}
Remember that MFC redefines the new operator within the debug version of MFC to track memory usage. That means you can't use the managed version of new. You'll get error C3828: "Placement arguments not allowed while creating instances of managed classes." To get rid of this error, use the following pragmas to undefine the new operator temporarily:
void UseAManagedType() {
#pragma push_macro("new")
#undef new
ArrayList* al;
al = new ArrayList();
#pragma pop_macro("new")
}
This lets you use managed types within an unmanaged application. However, most modern rich-client applications will be written using Windows Forms and ASP.NET, which we'll look at in the next two chapters.