C++/CLI to C++ Tips and Tricks

In my previous post, Writing Unit Tests in Visual Studio for Native C++, I described the approach I’m using to write unit tests for native C++ code by using C++/CLI, which is C++ code that runs inside the .NET runtime. Because of this “mixed” programming model, there are some techniques you may need to employ between C++ and C++/CLI code.

Class Instance Variables

The instance variables in C++/CLI classes are different from instance variables in native C++, which means you can’t mix the two blindly. For example, you can’t use native C++ classes as instance variables in your test class. The following, for example, will not compile:

 public ref class MyFixture
    MyClass m_instance;


You’ll get the following error message:

error C4368: cannot define 'm_instance' as a member of managed 'Tests::MyFixture': mixed types are not supported

So how do you deal with this? Instead of using a class as the type, you have to use pointers and then create/destroy the instance in the TestInitialize and TestCleanup code:

 public ref class MyFixture
    void Initialize()
        m_pInstance = new MyClass();

    void Cleanup()
        delete m_pInstance;

    MyClass *m_pInstance;

The methods marked by TestInitialize and TestCleanup run before and after each test method.

Passing a Pointer to an Instance Variable

C++/CLI instance variables have a type of interior_ptr<T> instead of the type you wrote in your code. This makes a difference if you attempt to pass either the address or a reference to this instance variable to a native C++ method or function. For example, given the class above, you might think you could write a call to one of your native methods like this:


Compile this and you’ll see this message:

error C2664: 'Tests::MyFixture::MyTest' : cannot convert parameter 2 from 'cli::interior_ptr<Type>' to 'MyClass **'

This error appears because .NET uses a heap—items on the heap can be moved as a result of garbage collection. In order to send a pointer to a native method/function, you need to “pin” the pointer for the duration of the call, which you can do like this:

 cli::pin_ptr<MyClass *> p = &m_pInstance;
SomeMethod(static_cast<MyClass **>(p));

Once the variable p either goes out of scope, or is assigned a new value, the pointer will be free to change again.

When you’re dealing with helper methods in your test code, you can also write this type of code:

void Helper(cli::interior_ptr<MyClass *> ppInstance)
    **ppInstance = new MyClass();