我有非托管课程。在那个类中,我有一个托管对象。现在我想在我的unmanged类中为托管对象创建一个pin_ptr。当我尝试这样做时,我收到此错误"错误C3265:无法在非托管pinnedProject
中声明托管_ ProjectWrapper
如何实现此目标?
这是代码。
class ProjectWrapper
{
private:
msclr::auto_gcroot<Project^> _project; // --> This works fine,
pin_ptr<msclr::auto_gcroot<Project^>> _pinnedProject; // ---> This gives error
public:
ProjectWrapper()
{
_project = gcnew Project();
pin_ptr<msclr::auto_gcroot<Project^>> anotherPinnedProject = &_project; // --> This one works,
//_pinnedProject = _project; // --> I want to use this instead of above live,
}
}
答案 0 :(得分:5)
关于pin_ptr<>
的MSDN文章并不羞于告诉你为什么这不起作用:
固定指针只能在堆栈上声明为非静态局部变量。
固定指针不能用作:
功能参数
函数的返回类型
班级成员
演员的目标类型。
这完全是一个很好的理由,这种对象固定是非常高效。根本不需要对CLR进行显式调用,当垃圾收集器遍历堆栈寻找根时,会发现该引脚。这要求对象引用是局部变量,编译器使用[pinned]属性在MSIL中发出它。还使用修复关键字在C#语言中公开。
所以,不能做,也不应该追求这个。将物体固定很长时间对于GC是非常不利的,它是路上的一块石头并且防止堆段被回收。你应该只确定你需要指针稳定的确切时刻,那个时刻只发生在使用指针的函数的代码内。
如果你想要解决这个问题,那么你需要回到沉重的引脚上。这需要GCHandle::Alloc(),传递GCHandleType :: Pinned。你从AddrOfPinnedObject()得到你需要的指针,使用Free()方法发布。