< Old To New C++ .Net 1 | Main | Visual C++ .Net Migration 3 >


 

 

Managed Extensions for C++ to

New C++ .NET Syntax Migration 2

 

 

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. Safe and Pure Images

  2. Metadata and Unnamed Classes

  3. Pure and Verifiable Code

  4. Pure (/clr:pure)

  5. Advantages of /clr:pure

  6. Limitations of /clr:pure

  7. Verifiable (/clr:safe)

 

 

Safe and Pure Images

 

A pure image will use a CLR version of the C run-time (CRT) library. However, the CRT is not verifiable, so you cannot use the CRT when compiling with /clr:safe. Examples of native code that cannot appear in a pure image include inline assembly, setjmp, or longjmp. Each entry point of a pure or safe image is managed. When compiling with /clr, the entry point is native. When compiling with /clr:safe, variables are by default appdomain, and cannot be per process. With /clr:pure, appdomain is the default, but you can use process variables.

When running a 32-bit .exe that was compiled /clr or /clr:pure on a 64-bit operating system, the application will be run under WOW64, which allows a 32-bit application to run by the 32-bit CLR on a 64-bit operating system. By default, an .exe compiled with /clr:safe will be run in the 64-bit CLR on a computer running a 64-bit operating system (on a 32-bit operating system the same .exe would run in the 32-bit CLR). However, it is possible that your safe application loads a 32-bit component. In that case, a safe image running under the operating system's 64-bit support will fail when it loads the 32-bit application (BadFormatException). To ensure that a safe image continues to run when it loads a 32-bit image on a 64-bit operating system, you must use /CLRIMAGETYPE (Specify Type of CLR Image) to change the metadata (.corflags), marking it to be run under WOW64. A sample command line follows (substitute your own entry symbol):

cl /clr:safe t.cpp /link /clrimagetype:pure /entry:?main@@$$HYMHXZ /subsystem:console

Metadata and Unnamed Classes

 

Unnamed classes will appear in metadata named as follows:

$UnnamedClass$crc-of-current-file-name$index$

where index is a sequential count of the unnamed classes in the compilation. For example, the following code sample will generate an unnamed class in metadata:

// clr_unnamed_class.cpp

// compile with: /clr /LD

class {} x;

Use ildasm.exe to view metadata. To set this compiler option in the Visual Studio development environment:

 

  1. Open the project's Property Pages dialog box.

  2. Click the Configuration Properties folder.

  3. Click the General property page.

  4. Modify the Common Language Runtime support property.

 

When /clr is enabled in a project's Property Pages dialog box, the compiler option properties that are not compatible with /clr will also be adjusted, as necessary. For example, if /RTC is set and then /clr is enabled, /RTC will be turned off.

 

Pure and Verifiable Code

 

For .NET Programming, Visual C++ supports the creation of three distinct types of components and applications: mixed, pure, and verifiable. All three are available through the /clr (Common Language Runtime Compilation) compiler option.

 

Mixed (/clr)

 

Mixed assemblies (compiled with /clr), contain both unmanaged and managed parts, making it possible for them to use .NET features, but still contain unmanaged code. This allows applications and components to be updated to use .NET features without requiring that the entire project be rewritten. Using C++ to mix managed and unmanaged code in this fashion is called C++ Interop.

 

Pure (/clr:pure)

 

Pure assemblies (compiled with /clr:pure) can contain both native and managed data types, but only managed functions. Like mixed assemblies, pure assemblies allow interop with native DLLs through P/Invoke, but C++ Interop features are not available. Moreover, pure assemblies cannot export functions that are callable from native functions because entry points in a pure assembly use the __clrcall calling convention.

 

Advantages of /clr:pure

 

The following are the advantageous using /clr:pure option.

  1. Better Performance: Because pure assemblies contain only MSIL, there are no native functions, and therefore no managed/unmanaged transitions are necessary. (Function calls made through P/Invoke are an exception to this rule.)

  2. AppDomain Awareness: Managed functions and CLR data types exist inside Application Domains, which affects their visibility and accessibility. Pure assemblies are domain-aware (__declspec(appdomain) is implied for each type) so accessing their types and functionality from other .NET components is easier and safer. As a result, pure assemblies interoperate more easily with other .NET components than mixed assemblies.

  3. Non-disk loading: Pure assemblies can be loaded in-memory and even streamed. This is essential for using .NET assemblies as stored procedures. This differs from mixed assemblies, which due to a dependency on the Windows loading mechanisms, must exist on disk in order to execute.

  4. Reflection: It is not possible to reflect over mixed executables, whereas pure assemblies provide full reflection support.

  5. Host Controllability: Because pure assemblies contain only MSIL, they behave more predictably and flexibly than mixed assemblies when used in applications that host the CLR and modify its default behavior.

 

 

Limitations of /clr:pure

 

The following are features not currently supported by /clr:pure.

  1. Pure assemblies cannot be called by unmanaged functions. Therefore pure assemblies cannot implement COM interfaces or expose native callbacks. Pure assemblies cannot export functions via __declspec(dllexport) or .DEF files. Also, functions declared with the __clrcall convention cannot be imported via __declspec(dllimport). Functions in a native module can be called from a pure assembly, but pure assemblies cannot expose native-callable functions, so exposing functionality in a pure assembly must be done through managed functions in a mixed assembly.

  2. ATL and MFC libraries are not supported by pure mode compilation in Visual C++ 2005.

  3. Pure .netmodules are not accepted as input to the C++ linker. However, pure .obj files are accepted by the linker, and .obj files contain a superset of information contained in netmodules.

  4. Compiler COM support (#import) is not supported, as this would introduce unmanaged instructions into the pure assembly.

  5. Floating point options for alignment and exception-handling are not adjustable for pure assemblies. As a result, __declspec(align) cannot be used. This renders some header files, such as fpieee.h, incompatible with /clr:pure.

  6. The GetLastError() function in the PSDK can give undefined behavior when compiling with /clr:pure.

 

Verifiable (/clr:safe)

 

The /clr:safe compiler option generates verifiable assemblies, like those written in Visual Basic and C#, conforming to requirements that allow the common language runtime (CLR) to guarantee that the code does not violate current security settings. For example, if security settings prohibit a component from writing to disk, the CLR can determine if a verifiable component meets this criterion before executing any of the code. There is no CRT support for verifiable assemblies. (CRT support is available to pure assemblies through a Pure MSIL version of the C Runtime library). Verifiable assemblies offer these advantages over pure and mixed assemblies:

  1. Increased security.

  2. Some situations require it (SQL components, for example).

  3. Future versions of Windows will increasingly require components and applications to be verifiable.

 

One disadvantage is that C++ interop features are not available. Verifiable assemblies cannot contain any unmanaged functions or native data types, even if they are not referenced by the managed code. Despite the use of the word "safe", compiling applications with /clr:safe does not mean there are no bugs; it just means that the CLR can verify the security settings at run time. Regardless of assembly type, calls made from managed assemblies to native DLLs via P/Invoke will compile, but may fail at runtime depending on security settings. There is one coding scenario that will pass the compiler but that will result in an unverifiable assembly: calling a virtual function through an object instance using the scope resolution operator. For example:

MyObj -> A::VirtualFunction();

 

Part 1 | Part 2 | Part 3 | Part 4

 


 

< Old To New C++ .Net 1 | Main | Visual C++ .Net Migration 3 >