Удобный способ вызова GC :: KeepAlive в сценариях C ++ / CLI? - PullRequest
3 голосов
/ 30 апреля 2009

Я пишу некоторые управляемые оболочки, используя C ++ / CLI. Проблема в том, что GC иногда удаляет объект, а я использую от него неуправляемые члены. (Я думаю, что это безумное поведение, но это другая тема). Для более подробной информации см .:

Финализатор запущен, когда его объект еще использовался http://blogs.msdn.com/cbrumme/archive/2003/04/19/51365.aspx

Мне нужен удобный способ звонить:

GC::KeepAlive(this);

в конце каждого метода. Для простых старых методов void это достаточно просто, но для методов, возвращающих значения, это немного сложнее.

int ComputeInt() {
   return m_unmanagedMember->LongRunningComputation();
}

должно быть преобразовано в:

int ComputeInt() {
   int tmp = m_unmanagedMember->LongRunningComputation();
   GC::KeepAlive(this);
   return tmp;
}

Это выглядит немного уродливо для меня.

Я рассмотрел класс защиты, который вызывает GC :: KeepAlive в dtor, но это вызовет вызовы ctor и dtor в каждом методе, который кажется немного чрезмерным.

Существует ли какое-либо волшебство C ++, которое позволило бы мне избежать переменной temp?

Редактировать

Я понял, что попытка +, наконец, поможет мне, т. Е.

int ComputeInt() {
   try {
      return m_unmanagedMember->LongRunningComputation();
   } finally {
      GC::KeepAlive(this);
   }
}

В конце я реализовал макрос для обработки этого:

#define KEEPALIVE_RETURN(x) try {\
    return x;\
} finally { System::GC::KeepAlive(this); }

1 Ответ

2 голосов
/ 06 мая 2009

Как насчет чего-то вроде (не проверяющего синтаксис)

template<class RType>
const RType& KeepAliveRet(Object^ o, const RType& ret)
{
    GC::KeepAlive(o);
    return ret;
} 


int ComputeInt() {
   return KeepAliveRet(this, m_unmanagedMember->LongRunningComputation());
}
...