C++ cli 如何创建自记忆钉扎C++/CLI类? 我在C++库中创建一个.NET包装器(我没有访问源代码),使用C++ +CLI。C++库需要调用在C++中使用的.NET委托。我使用McHal::GETFrimePoTeFrExtReATE给C++库类赋值调用函数。但是,当从非托管端回调此函数时,我需要确保.NET委托函数仍位于同一内存位置

C++ cli 如何创建自记忆钉扎C++/CLI类? 我在C++库中创建一个.NET包装器(我没有访问源代码),使用C++ +CLI。C++库需要调用在C++中使用的.NET委托。我使用McHal::GETFrimePoTeFrExtReATE给C++库类赋值调用函数。但是,当从非托管端回调此函数时,我需要确保.NET委托函数仍位于同一内存位置,c++-cli,C++ Cli,当然,最简单的方法是要求.NET库用户锁定.NET对象,但这并不是一个真正干净的设计,还允许用户射中自己的脚。更好的方法是设计.NET类,使其在创建时或由函数/事件触发时固定自身 我该如何设计这个?根据此链接,不能将内部~=固定指针作为对象成员。因此,这意味着可以将固定指针引用创建为静态变量或全局变量 所以我想做这两件事中的任何一件,但无法让它编译/工作 public ref class UserClass{ void createDotNetCPPWrapperClass() { m_

当然,最简单的方法是要求.NET库用户锁定.NET对象,但这并不是一个真正干净的设计,还允许用户射中自己的脚。更好的方法是设计.NET类,使其在创建时或由函数/事件触发时固定自身

我该如何设计这个?根据此链接,不能将内部~=固定指针作为对象成员。因此,这意味着可以将固定指针引用创建为静态变量或全局变量

所以我想做这两件事中的任何一件,但无法让它编译/工作

public ref class UserClass{
void createDotNetCPPWrapperClass()
{
    m_class = gcnew DotNetCPPWrapperClass;
}

DotNetCPPWrapperClass^ m_class

};


public ref class DotNetCPPWrapperClass{

static pin_ptr<DotNetCPPWrapperClass^> pinnedSelf;

DotNetCPPWrapperClass()
{
    pinnedSelf = this;
}
};
public ref class UserClass{
void createDotNetCPPWrapperClass()
{
m_class=gcnew DotNetCPPWrapperClass;
}
DotNetCPPWrapperClass ^m_类
};
公共引用类DotNetCPPWrapperClass{
静态引脚ptr钉扎自身;
DotNetCPPWrapperClass()
{
pinnedSelf=这个;
}
};

public ref class UserClass{
void createDotNetCPPWrapperClass()
{
m_class=gcnew DotNetCPPWrapperClass;
m_class->setupImportantstStuff();
}
DotNetCPPWrapperClass ^m_类
};
公共引用类DotNetCPPWrapperClass{
静态引脚ptr钉扎自身;
DotNetCPPWrapperClass(){}
void setupimportantsttuff()
{
pinnedSelf=这个;
}
};

GCHandle
将解决您的问题

public ref class Wrapper
{

GChandle thisHandle;
public:
  Wrapper() 
  {
    thisHandle = GCHandle.Alloc(this, GCHandleType::Normal);
  }

  ~Wrapper() // Dispose
  {
    if(thisHandle.IsAllocated)
      thisHandle.Free;
  }

  !Wrapper() // Finalize
  {
    //Native resource releasing
  }
}
现在有几点需要注意

  • 您不想长时间固定某个对象。锁定对象后,GC无法收集内存中在锁定对象之前对齐的对象,因为无法更改锁定对象的地址。因此,garbace收集变得毫无意义。请注意,我使用
    GCHandleType::Normal
    分配句柄不仅使其不可收集,而且使其可移动
  • 我不知道GC是否尝试收集具有分配句柄的对象,并调用该对象的终结器。在我看来,这没有意义,因为句柄阻止对象进行GC收集。因此,在C++/Cli中调用
    delete
    操作符,在C#中调用
    Dispose()
    并释放句柄是非常重要的。如果忘记调用这些,整个对象将成为内存泄漏

  • 您是否研究过使用框架提供的
    GCHandle
    HandleRef
    结构?使用Marshal::GetFunctionPointerForDelegate()的要点是您不必这样做。不要帮忙,请详细说明。“您必须手动防止垃圾收集器从托管代码收集委托。垃圾收集器不会跟踪对非托管代码的引用。”或者您是说GetFunctionPointerForDelegate将阻止重新定位,而不是垃圾收集?
    public class MyClass {
    
      private GCHandle gch;
    
      public MyClass() {
        gch=GCHandle.Alloc(this, GCHandleType.Pinned);
      }
    }
    
    public ref class Wrapper
    {
    
    GChandle thisHandle;
    public:
      Wrapper() 
      {
        thisHandle = GCHandle.Alloc(this, GCHandleType::Normal);
      }
    
      ~Wrapper() // Dispose
      {
        if(thisHandle.IsAllocated)
          thisHandle.Free;
      }
    
      !Wrapper() // Finalize
      {
        //Native resource releasing
      }
    }