< Old To New C++ .Net 2 | Main | Visual C++ .Net Migration 4 >


 

 

Managed Extensions for C++ to

New C++ .NET Syntax Migration 3

 

 

The code snippets used in this module if any, are the mix of Visual C++ .Net 2003 and 2005. If the old code used on VC++ 2005, compile with the /clr:OldSyntax option. The following are the topics in this part.

  1. How To: Migrate to /clr

  2. Compile with Visual C++ 2005

  3. Versions Prior to Visual C++ 2003

  4. Upgrading from Visual C++ 2003

  5. Upgrading from Managed Extensions for C++

  6. Convert C Code to C++

  7. Reconfigure Project Settings

  8. Create New Project Configurations

  9. Change Project Settings

  10. Precompiled Headers

 

 

How To: Migrate to /clr

 

This topic discusses issues that arise when compiling native code with /clr. /clr allows C++ modules to invoke and be invoked from .NET assemblies while retaining compatibility with unmanaged modules.

 

Known Issues Compiling Library Projects with /clr

 

Visual C++ 2005 contains some known issues when compiling library projects with /clr:

  1. When compiling an MFC ActiveX control project with /clr in the development environment, the build system will attempt to register the .dll with regasm and not regsvr32. You must manually register the control with regsvr32.

  2. When you create an ATL project and then enable /clr, the .c files will generate an error, because .c files cannot be compiled with /clr. However, if you change the file settings to compile the file with /TP, you will generate linker errors. The resolution is to compile the .c files as native (without /clr).

  3. Your code may query types at runtime with CRuntimeClass::FromName. However, if a type is in an MSIL .dll (compiled with /clr), the call to CRuntimeClass::FromName may fail if it occurs before the static constructors run in the managed .dll (you will not see this problem if the FromName call happens after code has executed in the managed .dll). To work around this problem, you can force the construction of the managed static constructor by defining a function in the managed .dll, exporting it, and invoking it from the native MFC application. For example:

// Extension DLL Header file:

__declspec(dllexport) void EnsureManagedInitialization ()

{

   // managed code that won't be optimized away

   System::GC::KeepAlive(System::Int32::MaxValue);

}

Compile with Visual C++ 2005

 

Before using /clr on any module in your project, first compile and link your native project with Visual C++ 2005. The following steps, followed in order, provide the easiest path to a /clr compilation. It is important to compile and run your project after each of these steps.

 

Versions Prior to Visual C++ 2003

 

If you are upgrading to Visual C++ 2005 from a version prior to Visual C++ 2003, you may see compiler errors related to the enhanced C++ standard conformance in Visual C++ 2003.

 

 

Upgrading from Visual C++ 2003

 

Projects previous built with Visual C++ 2003 should also first be compiled without /clr as Visual C++ 2005 has increased ANSI/ISO compliance and some breaking changes. The change that is likely to require the most attention is Security Enhancements in the CRT. Code that uses the CRT is very likely to produce deprecation warnings. These warnings can be suppressed, but migrating to the new Security-Enhanced Versions of CRT Functions is preferred, as they provide better security and may reveal security issues in your code.

 

Upgrading from Managed Extensions for C++

 

Projects built with Visual C++ .NET or Visual C++ 2003 that used Managed Extensions for C++ will require at least one change to project settings, as these extensions are now deprecated. As a result, code written with Managed Extensions for C++ won't compile under /clr. Use /clr:oldSyntax instead.

 

Convert C Code to C++

 

Although Visual C++ 2005 will compile C files, it is necessary to convert them to C++ for a /clr compilation. The actual filename doesn't have to be changed, you can use /Tp. Note that, although C++ source code files are required for /clr, it is not necessary to re-factor your code to use object-oriented paradigms. C code is very likely to require changes when compiled as a C++ file. The C++ type-safety rules are strict, so type conversions must be made explicit with casts. For example, malloc() returns a void pointer, but can be assigned to a pointer to any type in C with a cast:

int* a = malloc(sizeof(int));   // C code

int* b = (int*)malloc(sizeof(int));   // C++ equivalent

Function pointers are also strictly type-safe in C++, so the following C code requires modification. In C++ it's best to create a typedef that defines the function pointer type, and then use that type to cast function pointers:

NewFunc1 = GetProcAddress(hLib, "Func1");   // C code

typedef int(*MYPROC)(int);   // C++ equivalent

NewFunc2 = (MYPROC)GetProcAddress(hLib, "Func2");

C++ also requires that functions either be prototyped or fully defined before they can be referenced or invoked. Identifiers used in C code that happen to be keywords in C++ (such as virtual, new, delete, bool, true, false, etc.) must be renamed. This can generally be done with simple search-and-replace operations. Finally, whereas C-style COM calls require explicit use of the v-table and this pointer, C++ does not:

COMObj1->lpVtbl->Method(COMObj, args);  // C code

COMObj2->Method(args);  // C++ equivalent

Reconfigure Project Settings

 

After your project compiles and runs in Visual C++ 2005 you should create new project configurations for /clr rather than modifying the default configurations. /clr is incompatible with some compiler options and creating separate configurations lets you build your project as native or managed. When /clr is selected in the property pages dialog box, project settings not compatible with /clr are disabled (and disabled options are not automatically restored if /clr is subsequently unselected).

 

Create New Project Configurations

 

You can use Copy Settings From option in the New Project Configuration Dialog Box to create a project configuration based on your existing project settings. Do this once for the Debug configuration and once for Release configuration. Subsequent changes can then be applied to the /clr -specific configurations only, leaving the original project configurations intact. Projects that use custom build rules may require extra attention. This step has different implications for projects that use makefiles. In this case a separate build-target can be configured, or version specific to /clr compilation can be created from a copy of the original.

 

 

Change Project Settings

 

/clr can be selected in the development environment by following the instructions in /clr. As mentioned previously, this step will automatically disable conflicting project settings. When upgrading a managed library or web service project from Visual C++ 2003 to Visual C++ 2005, the /Zl compiler option will added to the Command Line property page. This will cause LNK2001. Remove /Zl from the Command Line property page to resolve. Or, add msvcrt.lib and msvcmrt.lib to the linker's Additional Dependencies property. For projects built with makefiles, incompatible compiler options must be disabled manually once /clr is added.

 

Precompiled Headers

 

Precompiled headers are supported under /clr. However, if you only compile some of your CPP files with /clr (compiling the rest as native) some changes will be required because precompiled headers generated with /clr are not compatible with those generated without /clr. This incompatibility is due to the fact that /clr generates and requires metadata. Modules compiled /clr can therefore not use precompiled headers that don't include metadata, and non /clr modules can't use precompiled header files that do contain meta data.

The easiest way to compile a project where some modules are compiled /clr is to disable precompiled headers entirely. (In the project Property Pages dialog, open the C/C++ node, and select Precompiled Headers. Then change the Create/Use Precompiled Headers property to "Not Using Precompiled Headers"). However, particularly for large projects, precompiled headers provide much better compilation speed, so disabling this feature is not desirable. In this case it's best to configure the /clr and non /clr files to use separate precompiled headers. This can be done in one step by multi-selecting the modules to be compiled /clr using the Solution Explorer, right-clicking on the group, and selecting Properties. Then change both the Create/Use PCH Through File and Precompiled Header File properties to use a different header file name and PCH file respectively.

 

 

Part 1 | Part 2 | Part 3 | Part 4

 


 

< Old To New C++ .Net 2 | Main | Visual C++ .Net Migration 4 >