AddThis Social Bookmark Button


Effective Interop with Managed C++

by John Bush

One of the new features of Visual Studio .NET 2003 is Windows Forms designer support for managed C++. Now you can write your Windows Forms applications in any of the "big three" .NET languages and get full support from the IDE.

You know what? I'm a long-time C++ programmer but, in all honesty, I don't know why Microsoft bothered. No one in his or her right mind would want to use managed C++ for new .NET application development. It's an odd hybrid language that still supports the familiar C++ syntax, but extends it with a bunch of proprietary keywords. Writing a .NET application in managed C++ requires extensive use of these new keywords, often resulting in a jumbled mess that C++ old-timers would barely recognize.

Despite all of that, don't write off managed C++ yet. If you can look past the superficial syntax issues, it offers unmatched power to developers who need legacy C++ applications to interoperate with .NET. The hybrid nature of managed C++ becomes a strength in these situations, because you're able mix your legacy C++ code with managed C++ in nearly any combination.

The flexibility of being able to mix managed and unmanaged code also introduces a host of new issues that aren't present in any other .NET language. In this article, I'll review some of these issues and present practical advice on how to deal with them.

Target Audience

The target audience for this article is developers who are interested in using managed C++ for interop. Ideally, you're a C++ developer with a working knowledge of .NET. I'm also going to assume that you're familiar with the basics of managed C++. If you have no previous experience with managed C++, an excellent prerequisite to this article is Sam Gentile's "Intro to Managed C++" series.

Mastering Visual Studio .NET

Related Reading

Mastering Visual Studio .NET
By Ian Griffiths, Jon Flanders, Chris Sells

Don't Break the Illusion

When using managed C++ to wrap unmanaged classes, the goal should be to make the managed wrapper class behave identically in all respects to a real managed class. Consumers of the wrapper class should have no idea that the class' underlying implementation is unmanaged code. As an example, consider how you might create a managed wrapper class for the following unmanaged C++ class' public interface:

class Customer

  const std::wstring& GetName() const;
  void SetName(const std::wstring& name);

  double CalculateAccountValue() const;

Here's my first attempt at making it managed:

__gc class ManagedCustomer1
  ManagedCustomer1() { m_pCustomer = new Customer(); }
  ~ManagedCustomer1() { delete m_pCustomer; }

  String* GetName()
    return m_pCustomer->GetName().c_str();

  void SetName(String* name)
    m_pCustomer->SetName( ToStdString(name) );

  double CalculateAccountValue(void)
    return m_pCustomer->CalculateAccountValue();

  Customer* m_pCustomer;

This is a typical managed wrapper class. It uses an embedded Customer pointer and manages its lifetime via ManagedCustomer1's constructor and destructor (actually, that's the finalizer in managed C++). Beyond that, ManagedCustomer1 simply provides managed versions of each function on Customer. (By the way, the function ToStdString() is a helper function I used to convert a managed string to an unmanaged STL string. Its implementation is not relevant here, but is based on information available in Tomas Restrepo's excellent MC++ FAQ.)

While there's nothing technically wrong with the ManagedCustomer1 wrapper class, I made a mistake by not updating the interface. It's often a bad idea to clone a C++ class interface in your managed wrapper class, because in doing so, you completely miss out on .NET features like properties, indexers, and interfaces. These features are expected by the consumers of your object and will be missed if they are not present.

Pages: 1, 2

Next Pagearrow