It’s quite common and easy to use legacy code from within a piece of managed code but sometimes it comes in handy to call managed code from legacy code.
__declspec(dllexport)
and the header file must not contain any reference to managed code:class __decldspec(dllexport) FooL { public: void BarL(); ... } // definition using namespace MyManaged::Foo; void FooL::BarL() { Foo^ f = gcnew Foo(); f->Bar(); }
And this is enough if you want to call managed code from a plain, C++ class. But sometimes you need pointers to managed object because, for example, you don’t want to create/destroy them every time you need to call a managed function. Also, we have to remember that a legacy class that has to be used in a legacy context cannot include managed code (at least, in its .h interface); to keep a reference to a managed object a void*
will be fine:
class __decldspec(dllexport) FooL { private: void* _foo; // foo is an opaque pointer public: void FooL(); void BarL(); ... }
The .cpp
code will use gcroot classes to wrap and pin the managed objects into memory:
#include <msclr\auto_gcroot.h> using namespace MyManaged::Foo; FooL::FooL() { Foo^ f = gcnew Foo(); // managed object // create a gcroot to keep the managed object in memory as far as we need msclr::auto_gcroot<Foo^>* handle = new msclr::auto_gcroot<Foo^>(); *handle = f; _foo = handle; }
It’s now easier to call the Bar()
function whenever we need:
void FooL::BarL() { msclr::auto_gcroot<Foo^>* handle = (msclr::auto_gcroot<Foo^>*) _foo; Foo^ f = handle->get(); f->Bar(); }
Using the pinned object we don’t have to re-create the Foo object each time we call the BarL()
function. To release and delete the pinned managed object:
~FooL::FooL() { msclr::auto_gcroot<Foo^>* handle = (msclr::auto_gcroot<Foo^>*) _foo; Foo^ f = handle->get(); if(f != nullptr) delete f; delete handle; _foo = NULL; }