C++/CLI Wrapping a Function that Returns a std::shared_ptr

匆匆过客 提交于 2019-12-01 08:23:48
Ben Voigt

shared_ptr is a native type, and managed objects can't have integral native subobjects.

However, as you note, managed objects can have pointers to native objects. What you need is a pointer to a shared_ptr, which will count as a reference to the BaseChannel object and keep it from being freed prematurely.

Of course, there are lots of reasons to use a smart pointer instead of a raw shared_ptr<BaseChannel>*. I've written a smart pointer which should be suitable, you can find it on codereview.stackexchange.com: "scoped_ptr for C++/CLI (ensure managed object properly frees owned native object)"


Example (not compile tested):

ref class ChannelUser
{
    clr_scoped_ptr<shared_ptr<BaseChannel>> chan_ptr;

public:
    ChannelUser( shared_ptr<BaseChannel>& chan ) : chan_ptr(new shared_ptr<BaseChannel>(chan)) {}
};

This automatically implements IDisposable and deletes the shared_ptr when Dispose or the finalizer runs, which in turn reduces the reference count on the BaseChannel.

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();
    }
};
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!