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.
Fixing Errors
Compiling with /clr may result in compiler, linker or runtime errors. The following section discusses the most common problems.
Metadata Merge
Differing versions of data types can cause the linker to fail because the metadata generated for the two types doesn't match. (This is usually caused when members of a type are conditionally defined, but the conditions are not the same for all CPP files that use the type.) In this case the linker fails, reporting only the symbol name and the name of the second OBJ file where the type was defined. It is often useful to rotate the order that OBJ files are sent to the linker to discover the location of the other version of the data type.
Loader Lock Deadlock
In Visual C++ .NET and Visual C++ 2003, initialization under /clr was susceptible to non-deterministic deadlock. This issue is known as "loader lock deadlock". In Visual C++ 2005, this deadlock is easier to avoid, it is detected and reported at runtime, and is no longer non-deterministic. Encountering the loader lock problem is still possible, but now it's much easier to avoid and fix.
Data Exports
Exporting DLL data is error-prone, and not recommended. This is because the data section of a DLL is not guaranteed to be initialized until some managed portion of the DLL has been executed. Reference metadata with the #using directive.
Type Visibility
Native types are now private by default. In Visual C++ .NET 2002 and Visual C++ 2003, native types were public by default. This can result in a native type not being visible outside the DLL. Resolve this error by adding public to these types. See Type and Member Visibility for more information.
Floating Point and Alignment Issues
The __controlfp is not supported on the common language runtime. The CLR will also not respect align (C++).
|
COM Initialization
The Common Language Runtime initializes COM automatically when a module is initialized (when COM is initialized automatically it’s done so as MTA). As a result, explicitly initializing COM yields return codes indicating that COM is already initialized. Attempting to explicitly initialize COM with one threading model when the CLR has already initialized COM to another threading model can cause your application to fail. COM initialization and associated error code should either allow for the case where COM is already initialized, or calls to CoInitialize and CoUninitialize can generally simply be removed. The common language runtime starts COM as MTA by default; use /CLRTHREADATTRIBUTE to modify this.
Performance Issues
You may see decreased performance when native C++ methods generated to MSIL are called indirectly (virtual function calls or using function pointers). When moving from native to MSIL, you will notice an increase in the size of your working set. This is because the common language runtime provides many features to ensure that programs run correctly. If your /clr application is not running correctly, you may want to enable C4793 (off by default).
Program Crashes on Shutdown
In some cases, the CLR can shutdown before your managed code is finished running. Using std::set_terminate and SIGTERM can cause this.
Using New C++ Features
After your application compiles, links, and runs, you can begin using .NET features in any module compiled with /clr. If you used Managed Extensions for C++, you can convert your code to use the new syntax.
New C++ Language Features
In Visual C++ 2005 Visual C++ includes new syntax for writing applications to target the common language runtime. This topic presents an overview of the new syntax. This syntax replaces the previous syntax, known as Managed Extensions for C++. Managed Extensions for C++ syntax is still available, but as a deprecated feature under /clr:oldSyntax compiler option. The new syntax is in effect by default when you use /clr.
CLR Data Type Keywords
The following table lists new keywords that have been added to the C++ language. Note that some keywords consist of two words separated by white space. These aggregate keywords are considered keywords despite the fact that used separately, they have different meanings. The word ref, for example, used without class is not a keyword and can be used as a regular identifier. Likewise, by itself class denotes a native class. But, used together, ref class defines a common language runtime (CLR) reference type.
Keyword | Old keyword | Context sensitive | Purpose |
ref class ref struct | __gc class __gc struct | No | Defines a CLR reference class |
value class value struct | __value class __value struct | No | Defines a CLR value class |
interface class interface struct | __interface class __interface struct | No | Defines a CLR interface |
enum class enum struct | enum enum | No | Defines a CLR enumeration |
property | __property | Yes | Defines a CLR property |
delegate | __delegate | Yes | Defines a CLR delegate |
event | __event | Yes | Defines a CLR event |
Table 2 |
Override Specifiers
The following keywords can be used to qualify override behavior for derivation. The new keyword is not new to C++ but is listed here because of the additional context in which it can be used. Some specifiers are also valid for native programming.
Keyword | Old Keyword | Context Sensitive | Purpose |
abstract | __abstract | Yes | Indicates functions or classes are abstract. |
new | - | No | Indicates that a function is not an override of a base class version. |
override | override | Yes | Indicates that a method must be an override of a base-class version. |
sealed | __sealed | Yes | Prevents classes from being used as base classes. |
Table 3 |
Keywords for Generics
The following keywords have been added to support generic types.
Keyword | Context sensitive | Purpose |
generic | No | Defines a generic type |
where | Yes | Specifies the constraints of a generic typedef |
Table 4 |
Miscellaneous New Keywords
The following keywords have been added to the C++ language.
Keyword | Context sensitive | Purpose |
finally | Yes | Indicates default exception handling behavior. |
for each | No | Enumerate elements of a collection. |
gcnew | No | Allocates types on the garbage-collected heap. |
initonly | Yes | Indicates a member can only be initialized at declaration or in a static constructor. |
literal | Yes | Creates a literal variable. |
nullptr | No | Indicates that a handle or pointer does not point at an object. |
Table 5 |
Non-Keyword Language Constructs
The following are language constructs that, while not official keywords, are fundamental to .NET programming. These constructs are implemented as templates. Most are defined in the cli Namespace.
Keyword | Purpose |
array | Type for representing CLR arrays. |
interior_ptr | Points to data inside reference types. |
pin_ptr | Points to CLR reference types to temporarily suppress the garbage collection system. |
safe_cast | Determines and executes the optimal casting method for CLR types. |
typeid | Retrieves a System.Type object describing the given type or object. |
Table 6 |
New C++ Operators
Two new operators have been added to C++ to support garbage-collected programming.
Operator | Purpose |
^ | Indicates a handle to an object located on the garbage-collected heap (instead of stack). |
% | Indicates a tracking reference. |
Table 7 |
More CLR Constructs
In addition to keywords and language constructs, the following reference includes the following CLR programming constructs for advanced topics. Well, you have to find it in your MSDN documentations.
Item/Topic | Description |
__identifier | Enables the use of C++ keywords as identifiers. |
.NET Framework equivalents to C++ Native Types | Lists the CLR types used in place of C++ integral types. |
appdomain __declspec modifier | __declspec modifier that mandates static and global variables exist per appdomain. |
C-Style casts with /clr | Describes how C-style casts are interpreted. |
__clrcall calling convention | Indicates the CLR-compliant calling convention. |
__cplusplus_cli | Predefined Macros. |
Custom attributes (C++) | Describes how to define your own CLR attributes. |
Exception Handling under /clr | Provides an overview of exception handling. |
Explicit overrides | Demonstrates how member functions can override arbitrary members. |
Friend Assemblies | Discusses how a client assembly can access all types in an assembly component. |
Implicit boxing | Demonstrates the conditions where values types are boxed. |
Compiler support for Type Traits | Discusses how to detect characteristics of types at compile time. |
managed, unmanaged pragmas | Demonstrates how managed and unmanaged functions can co-exist in the same module. |
process __declspec modifier | __declspec modifier that mandates static and global variables exist per process. |
Reflection in C++ | Demonstrates the CLR version of run-time type information. |
System::String handling in Visual C++ | Discusses compiler conversion of string literals to String. |
Type forwarding | Allows you to move a type in a shipping assembly to another assembly, such that, client code does not have to be recompiled. |
User-defined attributes | Demonstrates use-defined attributes. |
The #using Directive | Imports external assemblies. |
XML documentation (C++) | Explains XML-based code documentation using /doc (Process Documentation Comments) (C/C++). |
Table 8 |