Click here to Skip to main content
14,551,148 members

C++/CLI Library classes for interop scenarios

Rate this:
4.89 (35 votes)
Please Sign up or sign in to vote.
4.89 (35 votes)
20 Jun 2006Ms-PL
The article takes a brief look at some not so commonly used classes such as auto_handle, lock, and ptr.


Visual C++ 2005 comes with a bunch of helper classes that provide support for smart pointers, synchronization support, and COM wrappers. Most of them are very handy for interop scenarios, and this article will show examples on using these classes.

The auto_handle class

C++/CLI has syntactic support for deterministic disposal - and you can seemingly declare managed objects on the stack. Now, while this is extremely handy for most scenarios, sometimes, you end up with methods (mostly those in the BCL) that return handles to objects. This forces us to use the ^ syntax and to manually remember to call delete once the object is not required any more. The following code shows an example of one such method.

void Demo1A()
    StreamWriter^ sw;
        sw = File::CreateText("d:\\temp.txt");
        sw->WriteLine("This is a line of text");
        delete sw;

This is where the auto_handle class comes in handy. Add the following #include declaration to your code.

#include <msclr\auto_handle.h>

Now, you can rewrite the previous method as follows.

void Demo1B()
    msclr::auto_handle<StreamWriter> sw = File::CreateText("d:\\temp.txt");
    sw->WriteLine("This is a line of text");        

The auto_handle class overloads the -> operator and returns the underlying handle. So we can call StreamWriter methods just as if we were using a StreamWriter object. And when the destructor is called, delete is called on the underlying handle. If you need to persist the StreamWriter beyond the present scope, you can free the handle from the auto_handle object by calling release on it, as shown below.


Other operator overloads include those on =, !, and bool, so you can treat it like a pointer. And there's also a swap helper function that swaps handles between two auto_handle objects.

The gcroot and auto_gcroot classes

These two are probably quite well known and very commonly used, specially gcroot, since it existed in the old syntax too. But for the sake of completion, I include these here too. The gcroot template class wraps the BCL GCHandle class and allows us to declare and use a managed object as a member of a non-CLI class. The following code snippet shows a demonstration of the use of this class.

class Demo2A
    msclr::gcroot<StreamWriter^> m_sw;
        m_sw = File::CreateText("d:\\temp.txt");
        delete m_sw;

Notice how, I had to manually delete the StreamWriter object in the destructor. Using the auto_gcroot class, we can actually avoid having to do that on our own. Here's a modified class that uses auto_gcroot.

class Demo2B
    msclr::auto_gcroot<StreamWriter^> m_sw;
        m_sw = File::CreateText("d:\\temp.txt");

Well, now the destructor is gone. For most purposes, you should use the auto_gcroot class instead of the gcroot class, for obvious reasons. Remember to #include <msclr\gcroot.h> or <msclr\auto_gcroot.h> appropriately.

The _safe_bool class

_safe_bool is a value class that can be used in place of bool when providing an operator overload for bool. It prevents an implicit conversion to any integral type. Consider the following class.

ref class Demo3A
    operator bool() 
        return true;

Now the following code would compile fine, even when it may not have been intended to do so.

Demo3A a;
int y = a;

Here's how you would rewrite the class using a _safe_bool.

ref class Demo3B
    operator msclr::_detail_class::_safe_bool() 
        return msclr::_detail_class::_safe_true;

Now the following code will not compile.

Demo3B a;
int y = a;

You can also treat it like a bool, for most purposes.

if(a == msclr::_detail_class::_safe_false)

Both auto_handle and auto_gcroot use _safe_bool for their bool operator overloads. You need to #include <msclr\safebool.h> to use this class.

The ptr template - a COM wrapper class

This class is quite handy when you need to use a COM object as a member of a CLI class. The following #include is needed for this class.

#include <msclr\com\ptr.h>

The below code sample shows how to use the class.

ref class ManLink
    msclr::com::ptr<ILink> lnkptr;
        lnkptr.CreateInstance(__uuidof(Link)); // Create COM object
    void Resolve()
        lnkptr->ResolveLink(. . .); // Invoke COM method

The destructor will release the COM object (so you don't need to worry about it). There are several methods provided such as Attach which allows you to associate a COM pointer with a com::ptr object, Detach which makes the com::ptr object give up ownership of the COM object, and Release which releases the COM object. Note that Detach, increases the ref count before returning the interface pointer, and you are then responsible for releasing the object, once you are done using it.

The lock class

C# has the lock keyword which is internally implemented using the BCL Monitor class. C++/CLI does not have equivalent syntactic support, but the support library includes the lock class which (like the C# lock keyword) internally uses the Monitor class. You need to #include the following header file.

#include <msclr\lock.h>

Now, here's a sample showing how the lock class can be used.

ref class Demo4
    void DoSafeStuff()
        msclr::lock lk(this);
        Console::WriteLine("Starting work on thread {0}", 
        Thread::Sleep(300); // simulate complex task
        Console::WriteLine("Work ended on thread {0}", 

The lock class also comes with methods such as is_locked which returns true if a lock is held, a release method that releases the lock, an acquire method that gets a lock (and throws an exception if the lock could not be obtained), and a try_acquire method which is similar except that it does not throw an exception (instead it returns a bool). The following code shows how an instance of the above class is used from multiple threads, and how try_acquire is used to wait until all the threads are done executing.

int main(array<System::String ^> ^args)
    Demo4 d;
    msclr::lock lk(%d,msclr::lock_later); // defers locking
    for(int i=0; i<5; i++,(
        gcnew Thread(
        gcnew ThreadStart(%d, &Demo4::DoSafeStuff)))->Start()); 
    Console::WriteLine("Exiting main");
    return 0;

I think it's fantastic that C++/CLI allows us to smoothly write library implementations where a language feature does not directly exist.

Mapping delegates to non-CLI class methods

There's a delegate_proxy_factory class declared in <msclr\event.h> that allows you to map an event handler to a non-CLI class's member function. If you've done Windows Forms - MFC interop, then you presumably already know how to do this. But it's very useful even outside MFC Forms interop scenarios, and is also trivial to implement. Here's some code that shows how to map the FileSystemWatcher class's Renamed event to a native class method (albeit with managed arguments).

class Demo5
    msclr::auto_gcroot<FileSystemWatcher^> m_fsw;
    // Step (1)
    // Declare the delegate map where you map
    // native method to specific event handlers
        EVENT_DELEGATE_ENTRY(OnRenamed, Object^, RenamedEventArgs^)

        m_fsw = gcnew  FileSystemWatcher("d:\\tmp");
        // Step (2)
        // Setup event handlers using MAKE_DELEGATE
        m_fsw->Renamed += MAKE_DELEGATE(RenamedEventHandler, OnRenamed);
        m_fsw->EnableRaisingEvents = true;

    // Step (3)
    // Implement the event handler method
    void OnRenamed(Object^, RenamedEventArgs^ e)
        Console::WriteLine("{0} -> {1}",e->OldName, e->Name);


Essentially, these support library classes, make up for missing syntactic support in C++/CLI. Why add compiler overhead, when library implementations are trivial and equally effective? As usual, feedback (both critical and otherwise) is welcome.


This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)


About the Author

Nish Nishant
United States United States
Nish Nishant is a Principal Software Architect based out of Columbus, Ohio. He has over 17 years of software industry experience in various roles including Lead Software Architect, Principal Software Engineer, and Product Manager. Nish was a Microsoft Visual C++ MVP between 2002 and 2015.

Nish is an industry acknowledged expert in the Microsoft technology stack. He authored C++/CLI in Action for Manning Publications in 2005, and had previously co-authored Extending MFC Applications with the .NET Framework for Addison Wesley in 2003. In addition, he has over 140 published technology articles on and another 250+ blog articles on his WordPress blog. Nish is vastly experienced in team management, mentoring teams, and directing all stages of software development.

Contact Nish : If you are interested in hiring Nish as a consultant, you can reach him via his google email id voidnish.

Company Website :

Comments and Discussions

GeneralC2061 when trying to pass managed type to native function using auto_gcroot Pin
alleyes17-Mar-10 9:30
professionalalleyes17-Mar-10 9:30 
GeneralQuestion about managed/unmanaged code and /clr compilation Pin
El Bazza24-Sep-08 0:03
MemberEl Bazza24-Sep-08 0:03 
Questioncom::ptr versus Atl's CComPtr, or comdef.h's _com_ptr Pin
oshah10-Jul-06 0:41
Memberoshah10-Jul-06 0:41 
AnswerRe: com::ptr versus Atl's CComPtr, or comdef.h's _com_ptr Pin
Nish Nishant12-Jul-06 2:22
sitebuilderNish Nishant12-Jul-06 2:22 
GeneralRe: com::ptr versus Atl's CComPtr, or comdef.h's _com_ptr [modified] Pin
oshah13-Jul-06 10:04
Memberoshah13-Jul-06 10:04 
General[Message Removed] Pin
immetoz4-Oct-08 2:09
Memberimmetoz4-Oct-08 2:09 
General[Message Deleted] Pin
Mr. Say_how_it_is28-Jun-06 5:37
MemberMr. Say_how_it_is28-Jun-06 5:37 
GeneralRe: No 'delete' neccessary Pin
Nish Nishant28-Jun-06 5:49
sitebuilderNish Nishant28-Jun-06 5:49 
GeneralRe: No 'delete' neccessary Pin
Nemanja Trifunovic28-Jun-06 6:45
MemberNemanja Trifunovic28-Jun-06 6:45 
GeneralRe: No 'delete' neccessary [modified] Pin
Mr. Say_how_it_is28-Jun-06 7:45
MemberMr. Say_how_it_is28-Jun-06 7:45 
GeneralGreat Article Pin
Tomer Noy27-Jun-06 20:49
MemberTomer Noy27-Jun-06 20:49 
GeneralRe: Great Article Pin
Nish Nishant28-Jun-06 4:07
sitebuilderNish Nishant28-Jun-06 4:07 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Posted 20 Jun 2006


45 bookmarked