A Component in Managed Extensions for C++

Here is how the simple string component looks in Managed Extensions for C++:

Listing 1. Component in Managed Extensions for C++ (CompVC.cpp)

#using <mscorlib.dll>
using namespace System;

namespace CompVC {
   __gc public class StringComponent {
   private:
      String* StringsSet[];

   public:
      StringComponent() {
         StringsSet = new String*[4];
         StringsSet[0] = new String(L"Visual C++ String 0");
         StringsSet[1] = new String(L"Visual C++ String 1");
         StringsSet[2] = new String(L"Visual C++ String 2");
         StringsSet[3] = new String(L"Visual C++ String 3");
      }

     String* GetString(int index) {
       if ((index < 0) || (index >= StringsSet->Length)) {
         throw new IndexOutOfRangeException();
       }
       return StringsSet[index];
     }

      __property int get_Count() { return 
         StringsSet->Length; }
      };

};

As mentioned previously, you use the namespace statement to create a new namespace to encapsulate the classes you will be creating:

namespace CompVC {

Note that this namespace can be nested and split among multiple files. A single source-code file can also contain multiple namespaces that are not nested. Because the namespace can contain managed and unmanaged classes (unlike namespaces in Visual Basic and Visual C#, which have only managed classes), you use the modifier __gc to specify that the StringComponent class is managed:

__gc public class StringComponent {

This statement means that instances of StringComponent will now be created by the common language runtime and managed in the garbage collection heap. You could also have used the /clr compiler switch to make all classes in the program managed, whether or not they are prefixed with __gc.

The class constructor, which executes each time a new instance of the class is created, has the same name as the class and does not have a return type.

public:
    StringComponent() {

Here is the GetString method, which takes an integer and returns a string:

String* GetString(int index) {
    ...
    return StringsSet[index];
}

The throw statement in the GetString method highlights the runtime-based exception handling:

throw new IndexOutOfRangeException();

This statement creates a new object of type IndexOutOfRangeException and throws an exception, which is caught by the caller. Note that .NET exception handling requires that all exceptions — including those you define for your own use — must be derived from System::Exception.

**Note   **This error-handling mechanism replaces the one based on hResult that was used in previous versions of COM.

Finally, you create the read-only Count property:

__property int get_Count { return StringsSet->Count; }

Building the new Managed Extensions for C++ component is a little more complicated:

cl.exe /clr /Zi /c CompVC.cpp
link.exe -dll /debug /nod:libcpmt.lib kernel32.lib mscoree.lib /out:..\bin\CompVC.dll CompVC.obj

As with the simple Hello World Managed Extensions for C++ example, you need the /clr switch to tell the compiler to create a .NET managed-code assembly.

For convenience, the sample components for this tutorial are maintained in a ..\Bin subdirectory that is relative to the source code. To compile the component to that location, you simply specify the qualified file name using the /out parameter. You could also place the compiled components in the assembly cache, if they were going to be used with other programs. And even though you specified an output file with a .dll file name extension, you need the additional -dll switch to create a DLL rather than an executable file with a .dll file name extension.

See Also

A Component in Visual C# | A Component in Visual Basic | Clients for the Simple Components | Summary of Development Tutorial | Appendix A: Tools for Exploring Namespaces