本机智能指针变量的 c++/cli 包装器 class

c++/cli wrapper for variable of native smart-pointer class

我是 C# 和 C++/CLI 的新手,对它们不是很熟悉。我进行了搜索,但找不到一个非常简单的事情的现有解决方案(我想这应该很常见)。

我正在编写一个简单的 C++/CLI 项目(C# 中使用的 C++ 本机 dll 的包装器)。有很多示例如何为本机编写包装器 class:

class CNativeClass { 
    CNativeClass() {}
    void Foo() {}
}

public ref class CNativeClassWrapper {
public:
    CNativeClassWrapper() {
        _Wrapper = new CNativeClass;
    }
    ~CNativeClassWrapper() {
        this->!CNativeClassWrapper();
    }
    !CNativeClassWrapper() {
        delete _Wrapper;
        _Wrapper = nullptr;            
    }
    void Foo() {
        _Wrapper->Foo();
    }
private:
    CNativeClass* _Wrapper;
}

这是简化的示例代码。可能有更多原生 classes,可能有延迟初始化...很多次要但必要的代码。

原生 class 的变量 是否有隐藏所有这些细节的 包装器? 就像纯 C++ 中的智能指针模板。

此外, 如果本机 class 实际上是一个智能指针(我 90% 的情况下,我们使用 boost::shared_ptr<>),代码就会变得一团糟:

  • 检查可以是if ( _Wrapper )if ( *_Wrapper )甚至if ( _Wrapper && *_Wrapper ),
  • 访问方法 (*_Wrapper)->Foo();
  • 如何重置? (*_Wrapper).reset();_Wrapper->reset(); 都正确,但太混乱了。

有人知道这个的解决方案吗?

我认为 C++/CLI 框架没有内置 class,但您可以轻松设计自己的。

看看这个问题:auto_ptr or shared_ptr equivalent in managed C++/CLI classes

我不会使用智能指针。当包含托管 class 被处置或完成时,本机对象的托管包装器将负责释放本机对象。

好吧,我终于找到了这样的包装纸类:

  • 持有一般原生类:

    template <class T>
    public ref class native_auto_ptr
    {
    public:
        native_auto_ptr()
        {
            _pNative = new T;
        }
        native_auto_ptr(const native_auto_ptr<T>% rhs)
        {
            _pNative = new T( *rhs._pNative );
        }
        ~native_auto_ptr()
        {
            reset();
        }
        void reset()
        {
            delete _pNative;
            _pNative = nullptr;
        }
        T* ptr()
        {
            return _pNative;
        }
        T* operator->()
        {
            return _pNative;
        }
        operator bool()
        {
            return _pNative;
        }
        void operator=(const native_auto_ptr<T>% rhs)
        {
            *_pNative = *rhs._pNative;
        }
        void operator=(const T% rhs)
        {
            *_pNative = rhs;
        }
    protected:
        !native_auto_ptr()
        {
            reset();
        }
    private:
        T* _pNative;
    };
    
  • 持有shared_ptr<>:

    template <class T>
    public ref class native_shared_ptr
    {
    public:
        native_shared_ptr()
        {
            _spNative = new boost::shared_ptr<T>;
        }
        native_shared_ptr(const native_shared_ptr<T>% rhs)
        {
            _spNative = new boost::shared_ptr<T>;
            *this = rhs;
        }
        native_shared_ptr(const boost::shared_ptr<T>% rhs)
        {
            _spNative = new boost::shared_ptr<T>( rhs );
        }
        ~native_shared_ptr()
        {
            reset();
        }
        void reset()
        {
            delete _spNative;
            _spNative = nullptr;
        }
        T* operator->()
        {
            return _spNative->get();
        }
        operator bool()
        {
            return _spNative && *_spNative;
        }
        void operator=(const native_shared_ptr<T>% rhs)
        {
            *_spNative = *rhs._spNative;
        }
        void operator=(const boost::shared_ptr<T>% rhs)
        {
            *_spNative = rhs;
        }
    protected:
        !native_shared_ptr()
        {
            reset();
        }
    private:
        boost::shared_ptr<T>* _spNative;
    };
    

我很开心:)

  • 他们隐藏了 new/delete 个职位。
  • 他们很安全。
  • 它们的语法接近普通的智能指针,方便。

唯一的问题是带有参数的 ctors...(待定)