I have an unmanaged class that accepts a pointer to memory as its storage space.
e.g.
class MemBlock
{
void* mpMemoryBlock;
// Various other variables that manipulate the memory block goes here.
public:
MemBlock( void* pMemoryBlock ) :
mpMemoryBlock( pMemoryBlock )
{
}
// A load of code that does operation on the memory block goes here.
};
Now I'm trying to wrap this class for use from C#. Obviously I'd like to be able to pass something like a float[]
to the class. The obvious thing to do would be to use cli::pin_ptr
from the wrapper class.
public ref class MemBlockWrapper
{
MemBlock* mpMemBlock;
public:
MemBlockWrapper( array< float >^ fltArray )
{
cli::pin_ptr< float > pFltArray = &fltArray[0];
// Brilliant we can now pass this pinned array to the C++ code.
mpMemBlock = new MemBlock( (void*)pFltArray );
// Now the pin_ptr goes out of scope ...
}
}
However the pinned ptr is only valid so long as the cli::pin_ptr is in scope. The moment the constructor exits I can no longer guarantee that the memory block that the C++ class has is genuine.
Is there a way to pin a pointer for the lifetime of a class? I've done a lot of searching around and only found a method using "GCHandle" that appears to be purely for managed C++ (ie not C++/CLI). Can someone point me towards a way of pinning and unpinning a pointer deterministically?
A pinned
GCHandle
will do the job, it's usable from C++/CLI. Just make sure the handle is of the Pinned type, obviously.Here's an example:
I've added a destructor and a finalizer, this way you get the
Disposable
pattern along with safe cleanup even if you forget to dispose your wrapper.