I'm currently wrapping a C++ class with C++/CLI for .NET interoperability following the standard process of holding a native pointer in a managed class. In one instance, I have a native class that has a function like:
std::shared_ptr<BaseChannel> channelData(const int RunNumber);
I have already begun creating a wrapper class for BaseChannel
. However, if I pass the raw pointer to the constructor of the managed class, there are no guarantees on the lifetime of the object being pointed to by the managed class. I.e. the shared_ptr could go out of scope and the object will get deleted and the managed class will be left holding a dangling pointer.
What is the common solution for this situation?
UPDATE
@Ben: So I wrap the class that holds the method in the above question like so (let's say it is in a native class called Node
and it is being wrapped in a managed class called NodeRef:
ChannelUser^ NodeRef::ChannelData(int runNumber)
{
// mpNode is native class pointer of type Node held in managed class
// wrapper called NodeRef
std::shared_ptr<BaseChannel> spBaseChannel = mpNode->channelData(runNumber);
// ChannelUser is using clr_scoped_ptr to hold the shared_ptr
ChannelUser^ channelUser = gcnew ChannelUser(spBaseChannel);
return channelUser;
}
Because the shared_ptr does not have its reference count increased as it is passed to the managed class by reference, does that mean
that as long as this shared_ptr is in scope, the object it points to will still exist, because its reference count will be at least 1
? (ref C++ - passing references to std::shared_ptr or boost::shared_ptr)
Here's a managed shared_ptr<T>
. You can assign to it directly from a shared_ptr
and it'll take a copy that it will delete when the managed object is GC'd or disposed.
Examples:
m_shared_ptr<CupCake> cupCake0(new CupCake());
m_shared_ptr<CupCake> cupCake1 = new CupCake();
m_shared_ptr<CupCake> cupCake2 = shared_ptr<CupCake>(new CupCake());
m_shared_ptr<CupCake> cupCake3 = make_shared<CupCake>();
shared_ptr<CupCake> cupCake4 = (shared_ptr<CupCake>)cupCake3;
Code:
#pragma once
#include <memory>
template <class T>
public ref class m_shared_ptr sealed
{
std::shared_ptr<T>* pPtr;
public:
m_shared_ptr()
: pPtr(new std::shared_ptr<T>())
{}
m_shared_ptr(T* t) {
pPtr = new std::shared_ptr<T>(t);
}
m_shared_ptr(std::shared_ptr<T> t) {
pPtr = new std::shared_ptr<T>(t);
}
m_shared_ptr(const m_shared_ptr<T>% t) {
pPtr = new std::shared_ptr<T>(*t.pPtr);
}
!m_shared_ptr() {
delete pPtr;
}
~m_shared_ptr() {
delete pPtr;
}
operator std::shared_ptr<T>() {
return *pPtr;
}
m_shared_ptr<T>% operator=(T* ptr) {
delete pPtr;
pPtr = new std::shared_ptr<T>(ptr);
return *this;
}
T* operator->() {
return (*pPtr).get();
}
void reset() {
pPtr->reset();
}
};