【问题标题】:pin_ptr cannot declare a managed object in an unmanaged classpin_ptr 不能在非托管类中声明托管对象
【发布时间】:2015-02-16 12:27:36
【问题描述】:

我有非托管类。在那个类中,我有一个托管对象。现在我想要一个 pin_ptr 用于我的非托管类中的托管对象。当我尝试这样做时,我收到此错误“错误 C3265:无法在非托管 ProjectWrapper 中声明托管 _pinnedProject 我该如何实现?

这是代码。

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,
    }
}

【问题讨论】:

  • @KerrekSB 删除了标签。被误加了,Project^是c#类。 ProjectWrapper 是 c++,
  • 这个链接可以帮助你link你是否包含了所有需要的头文件

标签: c# c++-cli interop


【解决方案1】:

关于 pin_ptr&lt;&gt; 的 MSDN 文章并不羞于告诉你为什么这不起作用:

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

固定指针不能用作:

  • 功能参数

  • 函数的返回类型

  • 类的成员

  • 强制转换的目标类型。

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

所以,没有办法,也不应该追求这个。长时间固定一个对象对 GC 非常不利,它是道路上的一块石头,会阻止堆段被回收。您应该只在需要指针稳定的确切时刻固定,那个时刻只发生在使用指针的函数的代码内部。

如果您想摆脱这个问题,那么您需要回到沉重的针脚上。这需要GCHandle::Alloc(),通过 GCHandleType::Pinned。你从 AddrOfPinnedObject() 中得到你需要的指针,用 Free() 方法释放。

【讨论】:

  • 实际上,当构造函数完成时,我的 _project(托管)对象会丢失其信息。所以我不能在其他方法中使用 _project 。它给了我空异常,因为 GC 已经收集了对象。所以我需要找到一种方法来确保 GC 不会收集它。我发现 pin_ptr 是关键,
  • 还有这一行“pin_ptr<:auto_gcroot>> anotherPinnedProject = &_project;”在构造函数内部工作。为什么我不能成为班级成员?
  • 您需要再次阅读引用的 MSDN 文本。它在构造函数中也不起作用,只要构造函数代码正在运行,对象就会被固定,之后就不会被固定。存储指针是一个非常严重的错误,它会使您的代码随机失败。像我推荐的那样使用 GCHandle::Alloc() 还可以确保无法收集对象。
  • 我会尝试使用它。会告诉你结果的,谢谢,
猜你喜欢
  • 1970-01-01
  • 2023-04-09
  • 1970-01-01
  • 2011-07-12
  • 1970-01-01
  • 2021-07-15
  • 2019-07-14
  • 2018-03-19
  • 2016-02-21
相关资源
最近更新 更多