C++/CLI 包装返回 std::shared_ptr 的函数

发布于 2024-11-10 16:56:31 字数 1198 浏览 6 评论 0原文

我目前正在使用 C++/CLI 包装 C++ 类,以实现 .NET 互操作性,遵循在托管类中保存本机指针的标准流程。在一个实例中,我有一个本机类,其功能如下:

std::shared_ptr<BaseChannel> channelData(const int RunNumber);

我已经开始为 BaseChannel 创建一个包装类。但是,如果我将原始指针传递给托管类的构造函数,则无法保证托管类所指向的对象的生命周期。即,shared_ptr 可能超出范围,对象将被删除,托管类将保留一个悬空指针。

对于这种情况,常见的解决方案是什么?

更新

@Ben:所以我像这样包装了保存上述问题中方法的类(假设它位于一个名为 Node 的本机类中,并且它被包装在一个名为 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;
}

因为当通过引用传递给托管类时,shared_ptr 的引用计数没有增加,这是否意味着

只要这个shared_ptr在 范围,它指向的对象将 仍然存在,因为它的参考 计数至少为 1

? (ref C++ - 传递对 std::shared_ptr 或 boost::shared_ptr 的引用

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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

衣神在巴黎 2024-11-17 16:56:31

这是一个托管的 shared_ptr。您可以直接从 shared_ptr 分配给它,它会获取一个副本,当托管对象被 GC 或处置时,它将删除该副本。

示例:

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;

代码:

#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();
    }
};

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();
    }
};
鸢与 2024-11-17 16:56:31

shared_ptr 是本机类型,托管对象不能具有完整的本机子对象。

但是,正如您所注意到的,托管对象可以具有指向本机对象的指针。您需要的是一个指向 shared_ptr 的指针,它将被视为对 BaseChannel 对象的引用,并防止其过早释放。

当然,使用智能指针而不是原始 shared_ptr* 的原因有很多。我写了一个应该合适的智能指针,你可以在 codereview.stackexchange.com 上找到它: “C++/CLI 的scoped_ptr(确保托管对象正确释放拥有的本机对象)”


示例(未编译已测试):

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

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

这会自动实现 IDisposable 并在 Dispose 或终结器运行时删除 shared_ptr,从而减少 shared_ptr 上的引用计数>基本频道。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文