C ++/CLI:将相同的非托管对象包装在多个托管对象中 [英] C++/CLI: wrapping the same unmanaged object in multiple managed objects

查看:131
本文介绍了C ++/CLI:将相同的非托管对象包装在多个托管对象中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个具有两层的库,即非托管(C ++)和托管(C ++/CLI).非托管层包含逻辑和计算算法,而托管层为基于.NET的主机应用程序提供接口和可视化.托管层中的类将其类对应物包装在非托管层中,例如ManagedA包装UnmanagedA,ManagedB包装UnmanagedB.

I am developing a library which has two layers, unmanaged (C++) and managed (C++/CLI). The unmanaged layer contains the logics and the computation algorithms, while the managed layer provides interface and visualisation to a .NET-based host application. A class in the managed layer wraps its class counterpart in the unmanaged layer, e.g. ManagedA wraps UnmanagedA and ManagedB wraps UnmanagedB.

非托管层中的类具有查询方法,假设UnmanagedA :: B()返回UnmanagedB的实例.为了可视化,我需要将此实例包装在ManagedB实例中.问题是,如果我重复此过程两次,我将创建两个ManagedB实例,它们指向同一个UnmanagedB实例.因为处理了ManagedB实例,所以相同的UnmanagedB实例被删除了两次,这是不应该发生的.

Classes in the unmanaged layer have query methods, suppose UnmanagedA::B() returns an instance of UnmanagedB. For visualisation, I need to wrap this instance in a ManagedB instance. The problem is, if I repeat this process twice, I am creating two ManagedB instances which points to the same UnmanagedB instance. Because the ManagedB instances are disposed, the same UnmanagedB instance is deleted twice, which should not happen.

所以我想知道将非托管对象包装在托管对象中的最佳实践或策略.

这是一个模拟此行为的代码.我知道您不需要显式删除托管对象,但是我在这里使用它只是为了模拟删除顺序.

Here is a code which emulates this behaviour. I understand that you don't need to explicitly delete the managed objects, but I use it here just to emulate the deletion sequence.

非常感谢.

#include "stdafx.h"

using namespace System;

class UnmanagedB
{
public:
    UnmanagedB() {}
    ~UnmanagedB() {}

    int i = 0;
};

class UnmanagedA
{
public:
    UnmanagedA(UnmanagedB* pUnmanagedB)
    : m_pUnmanagedB(pUnmanagedB)
    {
    }

    ~UnmanagedA() {}

    UnmanagedB* B() { return m_pUnmanagedB; }

protected:
    UnmanagedB* m_pUnmanagedB;
};

public ref class ManagedA : IDisposable
{
public:
    ManagedA(UnmanagedA* pUnmanagedA)
        : m_pUnmanagedA(pUnmanagedA)
    {

    }

    ~ManagedA()
    {
        delete m_pUnmanagedA;
    }

private:
    UnmanagedA* m_pUnmanagedA;
};

public ref class ManagedB : IDisposable
{
public:
    ManagedB(UnmanagedB* pUnmanagedB)
        : m_pUnmanagedB(pUnmanagedB)
    {

    }

    ~ManagedB()
    {
        delete m_pUnmanagedB;
    }

private:
    UnmanagedB * m_pUnmanagedB;
};

int main(array<System::String ^> ^args)
{
    UnmanagedB* pUnmanagedB = new UnmanagedB();
    UnmanagedA* pUnmanagedA = new UnmanagedA(pUnmanagedB);

    ManagedB^ pManagedB1 = gcnew ManagedB(pUnmanagedA->B());
    ManagedB^ pManagedB2 = gcnew ManagedB(pUnmanagedA->B()); 
    delete pManagedB1;
    delete pManagedB2; // will crash here because the destructor deletes pUnmanagedB, which is already deleted in the previous line
    delete pUnmanagedA;
    return 0;
}

推荐答案

这是使用智能指针的典型情况.

This is a typical case using a smart pointer.

因此,请勿使用shared_ptr和shared_ptr存储UnmanagedA *和UnmanagedB *

So don't store UnmanagedA* and UnmanagedB* use shared_ptr and shared_ptr

由于托管类只能携带指向无人值守类的普通指针,因此您必须再次对其进行重定向并使用:

Becaus ethe managed class can only carry a plain pointer to an unmannged class you have to redirect it again and use:

shared_ptr<UnmanagedA>* pManagedA;

一个简单的访问器函数将帮助您使用指针:

A simple accessor function will help you to use the pointer:

shared_ptr<UnmanagedA> GetPtrA() { return *pManagedA; }

所有指向非托管类的普通指针都应该是shared_ptr实例.在您的主要使用make_shared而不是新的.或将new创建的指针直接指向shared_ptr ...

All plain pointer to the unmanaged classes should be shared_ptr instances. In your main use make_shared instead of new. Or direct the pointer created by new into a shared_ptr...

这里是一个重写的类:

public ref class ManagedA : IDisposable
{
public:
    ManagedA(shared_ptr<UnmanagedA> pUnmanagedA)
    {
        m_pUnmanagedA = new shared_ptr<UnmanagedA>();
        *m_pUnmanagedA = pUnmanagedA;
    }

    ~ManagedA()
    {
        delete m_pUnmanagedA;
    }

    void Doit()
    {
        GetPtrA()->DoSomething();
    }
private:
    shared_ptr<UnmanagedA>* m_pUnmanagedA;
    shared_ptr<UnmanagedA> GetPtrA() { return *m_pUnmanagedA; }
};

这篇关于C ++/CLI:将相同的非托管对象包装在多个托管对象中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆