我正在使用C ++ / CLI将某些功能从本机C ++ dll打包到.NET。我的一个本机类(UA类)具有一种方法,该方法返回对另一个本机类/对象(UB类)的引用。我在我的C ++ / CLI项目中都包装了两个类,如下所示:
//Unmanaged classes
class UA
{
public:
A(int x) : m_x(x) {}
int m_x;
};
class UB
{
public:
UB() : a(1) {}
UA& get_A(){return a;}
protected:
UA a;
};
// managed classes /CLI
public ref class A
{
internal:
A(UA* a) : m_ptr(a) {}
public:
A() : m_ptr(new UA(1)) {}
~A()
{
this->!A();
}
!A()
{
if (m_ptr != nullptr)
{
delete m_ptr;
}
}
private:
UA* m_ptr;
};
public ref class B
{
public:
B() : m_ptr(new UB()) {}
A^ get_A(){return gcnew A(&m_ptr->get_A())}
~B()
{
this->!B();
}
!B()
{
if (m_ptr != nullptr)
{
delete m_ptr;
}
}
private:
UB* m_ptr;
};
以上内容使用/clr
进行编译;但是,在C#.NET应用程序中测试时(请参见上文),我收到以下调试声明错误:
// C#.NET app
B b = new B();
A = b.get_A();
此错误发生在托管包装(!A())
的终结器class A
中。特别是,当GC尝试删除本机指针时,会引发此错误。我想这只是为什么我没有使用new关键字创建此实例。您是否认为最好在本机C ++中使用副本构造函数,然后使用new关键字创建托管包装类?
例如:
//Unmanaged classes
class UA
{
public:
A(int x) : m_x(x) {}
A(const A& a)
{
m_x = a.m_x;
}
int m_x;
};
然后托管的A和B包装器将是:
// managed classes /CLI
public ref class A
{
internal:
A(UA* a) : m_ptr(a) {}
public:
A() : m_ptr(new UA(1)) {}
~A()
{
this->!A();
}
!A()
{
if (m_ptr != nullptr)
{
delete m_ptr;
}
}
private:
UA* m_ptr;
};
public ref class B
{
public:
B() : m_ptr(new B()) {}
A^ get_A(){return gcnew A(new UA(&m_ptr->get_A()))}
~B()
{
this->!B();
}
!B()
{
if (m_ptr != nullptr)
{
delete m_ptr;
}
}
private:
UB* m_ptr;
};
是否有其他方法可以返回对C#中非托管对象的引用?抱歉,如果我做一些根本错误的事情,那么我对C ++ / CLI的经验将很少。我也看到了这个post;但是,似乎已被接受的答案提出了我首先实施的解决方案。 感谢您的帮助/建议。
答案 0 :(得分:0)
这仅仅是由于这样的事实,当您调用b.get_A()
时,它会调用内部构造函数A(UA* a) : m_ptr(a) {}
,该构造函数仅存储指向类型为{{1的对象的字段a
}的指针}}。然后,析构函数将尝试删除无法使用的指针。
这与C ++ / CLI无关,只是与分配和删除对称。在这种情况下,只需删除您的公共构造函数UB
即可进行分配,并删除那些析构函数,它将起作用。