pin_ptr无法在非托管类中声明托管对象

时间:2015-02-16 12:27:36

标签: c# c++-cli interop

我有非托管课程。在那个类中,我有一个托管对象。现在我想在我的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,
    }
}

1 个答案:

答案 0 :(得分:5)

关于pin_ptr<>的MSDN文章并不羞于告诉你为什么这不起作用:

  

固定指针只能在堆栈上声明为非静态局部变量。

     

固定指针不能用作:

     
      
  • 功能参数

  •   
  • 函数的返回类型

  •   
  • 班级成员

  •   
  • 演员的目标类型。

  •   

这完全是一个很好的理由,这种对象固定是非常高效。根本不需要对CLR进行显式调用,当垃圾收集器遍历堆栈寻找根时,会发现该引脚。这要求对象引用是局部变量,编译器使用[pinned]属性在MSIL中发出它。还使用修复关键字在C#语言中公开。

所以,不能做,也不应该追求这个。将物体固定很长时间对于GC是非常不利的,它是路上的一块石头并且防止堆段被回收。你应该只确定你需要指针稳定的确切时刻,那个时刻只发生在使用指针的函数的代码内。

如果你想要解决这个问题,那么你需要回到沉重的引脚上。这需要GCHandle::Alloc(),传递GCHandleType :: Pinned。你从AddrOfPinnedObject()得到你需要的指针,使用Free()方法发布。