0

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

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

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

4

1 回答 1

0

处理混合模式项目时的经典情况,你的建议是OK的!

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

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

于 2013-06-14T00:03:33.487 回答