Visual C++ and CodeDom

The types within the System.CodeDom namespace are extremely important to most Managed C++ applications, regardless of whether the code actually uses these types directly. Wizard-generated code has always formed a large part of Visual C++ applications and, by virtue of its multi-language support, .NET needed a technology that separated the definition of logical code graphs from the actual production of source code. CodeDom is the technology that provides this capability, and through the use of language-specific code providers, you can convert an abstract CodeDom graph into a source code file in any language that has a provider available.

This article covers CodeDom from a C++ perspective. (For an introduction to CodeDom from a language-agnostic perspective, check out Paul Kimmel’s “Writing Code Generators with the Code Document Object Model“.) An article on CodeDom from the perspective of a particular language may seem a little strange, but the Managed C++ code provider did not have the same good start that code providers for other Microsoft language such as C# and VB.NET did. This has had a significant impact on Visual C++.NET as a product today (as you will soon learn).

Before going into the specifics of CodeDom, a quick trip into recent history would be worthwhile to examine the relationship between Visual C++ and .NET. These reflections are entirely my own and don’t necessarily represent Microsoft’s view of the product. When .NET was publicly previewed in 2000 and 2001, C# was The .NET Language. It had the most mature compiler and a great wealth of sample code—and the fact that the Framework libraries were written in C# gave a pretty good indication that it was going to be the language of choice for .NET development. Visual Basic had a massive user base, a reasonably weak native code offering, and a very vocal community that had pockets of strong resistance to change. These factors created a situation that Microsoft is still dealing with today, but despite some problems, Visual Basic.NET has been a very adequate tool for developing .NET code from day one.

C++ and Visual C++ were different. They had a strong and mature user community, reasonable libraries for native Windows and COM development, great standard libraries for containers, strings, streams, and algorithms, and a massive existing code base that couldn’t be migrated to the .NET runtime in an automated way (even if the migration made sense, which it didn’t for many applications). These factors meant that C++ required preserving the native compiler, and Visual C++ had to be very good at interoperability between managed and native code. This interoperability work succeeded remarkably well, and placed Visual C++ in the position as the tool of choice for any interoperability task.

Work on native and interoperability features did come at a cost, however. Many features that programmers take for granted in other managed languages were missing in Visual C++. The original version of Visual C++.NET lacked many features, including designer support for Windows Forms and ASP.NET.

The root cause of many of the missing features in the original release of Visual C++.NET was the lack of a Managed C++ CodeDom code provider. Visual Studio.NET and the Framework tools use CodeDom for nearly all their Code-generation needs. Therefore, the lack of CodeDom support obviously locks a tool out of a wide range of functionality, or at least makes implementing these features extremely difficult. Some of the places where CodeDom is used include WSDL wrappers, strongly-typed DataSet generation, and the various forms designers.

The instructions for the command-line WSDL utility illustrate the difficulty in using Managed C++ with the Framework tools. They state (in part):


The language to use for the generated proxy class. Choose from ‘CS’, ‘VB’, ‘JS’, ‘VJS’ or provide a fully-qualified name for a class implementing System.CodeDom.Compiler.CodeDomProvider. The default is ‘CS’ (CSharp). Short form is ‘/l:’.

Conspicuously absent is Managed C++. For the programmer who wants to use the output of this tool in a C++ project, an understanding of CodeDom is required, as well as knowledge of how to find and provide the name of the Managed C++ CodeDomProvider. This is hardly the ideal situation for a language that would like to include itself as a first-class .NET language.

Fortunately, Visual C++.NET 2003 does include a CodeDom provider. However, the MSDN Library does not properly document it, it does not live in the System assembly like the CSharpCodeProvider and VBCodeProvider, and Visual C++.NET 2003 does not include an ASP.NET Forms designer. The full name of the CodeDom provider is Microsoft.MCpp.MCppCodeProvider, and it lives in the MCppCodeDomProvider assembly (MCppCodeDomProvider.dll), which is installed in the folder C:Program FilesMicrosoft Visual Studio .NET 2003Common7IDEPublicAssemblies and in the GAC.

The lack of documentation is not an overly serious problem because CodeDom is well documented in the MSDN Library and in many independent articles and books. All CodeDom providers implement a common set of interfaces, which is well documented, and using a specific language is simply a matter of changing a few letters after the new operator.

The lack of ASP.NET designer support is an unfortunate omission, but it is worth emphasizing that this feature does not mean than Managed C++ cannot produce an ASP.NET Web site. A C++ site won’t have the same code-behind abilities as C# or VB.NET, but by deriving from the appropriate types within the System.Web namespace, a Managed C++ ASP.NET site is possible. A much easier solution is to use C# for the front-end and call C++ assemblies from the code-behind page. Language similarities make using C# in this manner easy, even if the language is entirely new to the developer, and allows the ASP.NET designer to be utilized.

Using the Managed C++ Code Provider

Despite a number of shortfalls, the Managed C++ Code Provider is still very useful. The following syntax enables you to use it with command-line tools, such as XSD.exe and WSDL.exe, that can accept the type name of a CodeDomProvider-derived class:


This statement generates a header file that allows the Web service to be called in a strongly typed, simple manner. The example parses the webservice WSDL to produce an abstract code-graph, which the MCppCodeDomProvider type then converts into Managed C++ code. Many C++ programmers will object to placing declaration and implementation in the one, but this problem is largely a consequence of the interfaces that the C++ code DOM types are implementing (in particular ICodeGenerator.GenerateCodeFromCompileUnit, which is the method used to actually write a compile unit to a stream). The method accepts only a single stream, and the CodeDom model has no concept of separate header and source files.

Using the Managed C++ Code Provider with code is just as easy as using it with tools. Simply reference the MCppCodeDomProvider assembly, and in the places a code provider is required, use the MCppCodeProvider type. Rather than build a full code graph from scratch, this article uses the reasonably complex graph Paul Kimmel built in the sample code accompanying “Writing Code Generators with the Code Document Object Model.” In that sample, Paul built a simple Windows Forms form. His code outputted VB source code, but by changing the two lines that create the VB code provider to use the Managed C++ code provider (after adding a reference to it) and changing the file extension of the output file from “vb” to “h”, the sample can produce Managed C++ code. The changes to the original code are in italics:

' Write the source code
Dim Stream As StreamWriter = New StreamWriter("out.h")
   Dim Generator As ICodeGenerator = _
      (New Microsoft.MCpp.MCppCodeProvider).CreateGenerator

   Generator.GenerateCodeFromCompileUnit( _
      Unit, Stream, Nothing)
End Try

' Create the compiler
Dim Compiler As ICodeCompiler = _
   (New Microsoft.MCpp.MCppCodeProvider).CreateCompiler()

By running the VB.NET sample with these changes, the following code is produced:

#pragma once

#using <mscorlib.dll>

namespace codeguru {namespace com {
   using namespace System;
   using namespace System::Drawing;
   using namespace System::Windows::Forms;
   using namespace System::Xml;
   using namespace System::Data;
   using namespace System;
   public __gc class Form1;
   public __gc class Form1 : public System::Windows::Forms::Form {
      private: System::ComponentModel:: IContainer * components;
      public: Form1();
      protected: virtual System::Void Dispose
         (System::Boolean disposing);
      private: [System::Diagnostics::DebuggerStepThrough]
      System::Void InitializeComponent();
   inline Form1::Form1() {
   inline System::Void Form1::Dispose(System::Boolean disposing) {
      if (disposing) {
         if ((components != 0)) {
   inline System::Void Form1::InitializeComponent() {
      this->components = new System::ComponentModel::Container();

More by Author

Must Read