C++ cli C++/CLI:通过C++;类ptr到非托管方法

C++ cli C++/CLI:通过C++;类ptr到非托管方法,c++-cli,pointers,C++ Cli,Pointers,我得到了一个第三方C/C++库(.dll、.lib、.exp和.h),我需要在我们的C#应用程序中使用它 第三方图书馆.h包含 class AClass { public: typedef enum { green = 7, blue = 16 } Color; virtual int GetData()=0; virtual int DoWork(Color, char *)=0; }; void * Func1(int, AClass **aCla

我得到了一个第三方C/C++库(.dll、.lib、.exp和.h),我需要在我们的C#应用程序中使用它

第三方图书馆.h包含

class AClass {
 public:
  typedef enum {
      green = 7,
      blue = 16
  } Color;
  virtual int GetData()=0;
  virtual int DoWork(Color, char *)=0;
};

void * Func1(int, AClass **aClass);
在我的C++/CLI代码中,我已经完成了这项工作

#include "ThirdPartyLibrary.h"
using namespace System;
using namespace System::Runtime::InteropServices;

namespace Wrapper {
public ref class MyBridgeClass
{
private:
  AClass* pAClass;

public:
  // C# code will call this method
  void AMethod (int x)
  {
    int y = x+10;
    Func1 (y, &(this->pAClass));  // <-- error!
  }
}
}
#包括“第三方图书馆.h”
使用名称空间系统;
使用名称空间System::Runtime::InteropServices;
名称空间包装器{
公共引用类MyBridgeClass
{
私人:
AClass*pAClass;
公众:
//C代码将调用此方法
虚空法(整数x)
{
int y=x+10;

Func1(y,&(this->pAClass));//出现此错误的原因是托管内存的工作方式

在托管类中,您已经定义了一个指针。该指针的地址是托管对象的一部分,在垃圾回收器运行时可以更改。这就是为什么您不能将
&pAClass
传递给该方法,GC可以更改该地址的实际内容

要解决此问题,您可以做以下几件事:

您可以创建一个非托管帮助器类来保存
AClass*
成员。如果该指针需要在调用此方法之后保持有效,或者如果要保存大量非托管指针,我会这样做

struct UnmanagedHolder
{
    AClass* pAClass;
};

public ref class MyBridgeClass
{
private:
  // must create in constructor, delete in destructor and finalizer.
  UnmanagedHolder* unmanaged; 

public:
  // C# code will call this method
  void AMethod (int x)
  {
    int y = x+10;
    Func1 (y, &(this->unmanaged->pAClass));
  }
};
如果您只需要指针在AMethod内有效,并且指针在调用Func1后不需要保持有效,那么您可以使用pin_ptr

void AMethod (int x)
{
  int y = x+10;
  pin_ptr<AClass*> pin = &(this->pAClass);
  Func1 (y, pin);
}
void-AMethod(int x)
{
int y=x+10;
pin_ptr pin=&(此->pAClass);
函数1(y,pin);
}

出现此错误的原因是受管内存的工作方式

在托管类中,您已经定义了一个指针。该指针的地址是托管对象的一部分,在垃圾回收器运行时可以更改。这就是为什么您不能将
&pAClass
传递给该方法,GC可以更改该地址的实际内容

要解决此问题,您可以做以下几件事:

您可以创建一个非托管帮助器类来保存
AClass*
成员。如果该指针需要在调用此方法之后保持有效,或者如果要保存大量非托管指针,我会这样做

struct UnmanagedHolder
{
    AClass* pAClass;
};

public ref class MyBridgeClass
{
private:
  // must create in constructor, delete in destructor and finalizer.
  UnmanagedHolder* unmanaged; 

public:
  // C# code will call this method
  void AMethod (int x)
  {
    int y = x+10;
    Func1 (y, &(this->unmanaged->pAClass));
  }
};
如果您只需要指针在AMethod内有效,并且指针在调用Func1后不需要保持有效,那么您可以使用pin_ptr

void AMethod (int x)
{
  int y = x+10;
  pin_ptr<AClass*> pin = &(this->pAClass);
  Func1 (y, pin);
}
void-AMethod(int x)
{
int y=x+10;
pin_ptr pin=&(此->pAClass);
函数1(y,pin);
}

我知道固定,但我没有意识到非托管字段仍然在托管堆上分配。我在桥接类“ctor”和“if”(this->unmanaged)中添加了一个“this->unmanaged=new UnmanagedHolder()”将此->未管理字段删除到网桥类终结器。我知道钉住,但我没有意识到未管理字段仍在托管堆上分配。我将“this->unmanaged=new UnmanagedHolder()”添加到网桥类“ctor”,并将“if(this->unmanaged)删除此->未管理字段”添加到网桥类终结器。