用c++/cli互操作管理内存

本文关键字:管理 内存 互操作 cli c++ | 更新日期: 2023-09-27 18:16:42

我见过的大部分代码都删除了终结器/析构函数中的指针:

public ref class CPPObjectWrapper
{
private:
    CPPObject *_cppObject;
public:
    CPPObjectWrapper()
    {
        _cppObject = new CPPObject();
    }
    CPPObjectWrapper(IntPtr ^ptr)
    {
        _cppObject = ptr->ToPointer();
    }
    ~CPPObjectWrapper()
    {
        delete _cppObject;
        _cppObject = 0;
    }
    !CPPObjectWrapper()
    {
        if (_cppObject != 0) delete _cppObject;
    }
    IntPtr^ GetPointer()
    {
        return gcnew IntPtr(_cppObject);
    }
}

我的问题是,如果你的包装库做这样的事情,标准做法是什么:

void AddObject(CPPObject *cppObject)
{
    // adds to a std::list
}
CPPObject* FindObject(/* criteria */)
{
    // return reference to std::list item based on criteria
}

如果你的c#包装器这样做:

void AddObject(CPPObjectWrapper ^cppObject)
{
    _internal->addObject(cppObject->GetPointer()->ToPointer());
}
CPPObjectWrapper^ FindObject(/* criteria */)
{
    CPPObject *cppObject = _internal->findObject(/* criteria */);
    return gcnew CPPObjectWrapper(gcnew IntPtr(cppObjet));
}

您遇到内存问题,因为您的托管对象不应该删除指针,因为它在另一个对象中被引用。返回时也是如此。您会简单地添加功能来告诉托管包装器在所有权转移时不要释放内存吗?

用c++/cli互操作管理内存

处理混合模式项目时的经典情况,您的建议是可以的!

在构造函数中有一个bool值是有意义的,它告诉构造函数如果在另一个非包装对象中使用了相同的对象,则不要销毁指针。理想的情况是每个对象都被包装,并且销毁将由CLR完成。

您可以创建一个泛型基类(使用您已经拥有的代码),在子类中默认设置bool值。您可以保证多次使用此功能。另一个技巧是从CLR析构函数(!)调用一个虚的OnFinalize()方法,该方法可以在子类中执行特殊操作,例如调用本机库提供的一些特殊的自由函数。