C ++ / CLI: вернуть ссылку на неуправляемый объект в приложении C # .NET - PullRequest
0 голосов
/ 03 мая 2019

Я обертываю некоторые функциональные возможности от родной C ++ dll до .NET с C ++ / CLI. Один из моих нативных классов (класс UA) имеет метод, который возвращает ссылку на другой нативный класс / объект (класс UB). Я обернул оба класса в своем проекте C ++ / CLI следующим образом:

//Unmanaged classes
class UA 
{
public:
A(int x) : m_x(x) {}
int m_x;
};

class UB 
{
public:
UB() : a(1) {}
UA& get_A(){return a;}
protected:
UA a;
};

// managed classes /CLI
public ref class A
{
internal:
A(UA* a) : m_ptr(a) {}
public:
A() : m_ptr(new UA(1)) {}
~A()
{
  this->!A();
}
!A()
{
  if (m_ptr != nullptr)
  {
     delete m_ptr;
  }
}
private:
UA* m_ptr;
};

public ref class B 
{
public:
B() : m_ptr(new UB()) {}
A^ get_A(){return gcnew A(&m_ptr->get_A())}
~B()
{
  this->!B();
}
!B()
{
  if (m_ptr != nullptr)
  {
     delete m_ptr;
  }
}
private:
UB* m_ptr;
};

Выше компилируется с /clr; однако при тестировании в приложении C # .NET я получаю сообщение об ошибке отладки.

// C#.NET app
B b = new B();
A = b.get_A();

Эта ошибка возникает в финализаторе (!A()) управляемого переноса class A. В частности, он возникает, когда GC пытается удалить собственный указатель. Я думаю, это происходит просто потому, что я не создал этот экземпляр с новым ключевым словом. Как вы думаете, было бы лучше использовать конструктор копирования в нативном C ++, а затем создать управляемый класс обтекания с новым ключевым словом?

Например:

//Unmanaged classes
class UA 
{
public:
A(int x) : m_x(x) {}
A(const A& a)
{
  m_x = a.m_x;
}
int m_x;
};

И тогда управляемые оболочки A и B будут:

// managed classes /CLI
public ref class A
{
internal:
A(UA* a) : m_ptr(a) {}
public:
A() : m_ptr(new UA(1)) {}
~A()
{
  this->!A();
}
!A()
{
  if (m_ptr != nullptr)
  {
     delete m_ptr;
  }
}
private:
UA* m_ptr;
};

public ref class B 
{
public:
B() : m_ptr(new B()) {}
A^ get_A(){return gcnew A(new UA(&m_ptr->get_A()))}
~B()
{
  this->!B();
}
!B()
{
  if (m_ptr != nullptr)
  {
     delete m_ptr;
  }
}
private:
UB* m_ptr;
};

Есть ли другой способ вернуть ссылку на неуправляемый объект в C #? Извиняюсь, если я делаю что-то в корне неправильно, у меня очень небольшой опыт работы с C ++ / CLI. Я тоже видел этот пост ; однако, кажется, что принятый ответ предлагает решение, которое я впервые реализовал. Я ценю любую помощь / предложение.

1 Ответ

0 голосов
/ 03 мая 2019

Это просто потому, что когда вы вызываете b.get_A(), это вызывает ваш внутренний конструктор A(UA* a) : m_ptr(a) {}, который просто хранит указатель на поле a объекта типа UB. Затем деструктор попытается удалить этот указатель, который не может работать.

Это не имеет ничего общего с C ++ / CLI, просто быть симметричным с выделениями и удалениями. В этом случае просто удалите ваш публичный конструктор A(), который выполняет выделение, а также эти деструкторы, и это будет работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...