Как правильно получать вызовы виртуальных методов C ++ в приложение Objective-C ++? - PullRequest
1 голос
/ 28 мая 2019

У меня есть библиотека переносимого сетевого кода на C ++, которая широко использует абстрактные и полуабстрактные интерфейсные классы, например, такие как:

// Semi-abstract interface for any C++ object that wants to
// be notified about network events
class INetworkEventReceiver
{
public:
   INetworkEventReceiver(INetworkEventGenerator * master)
      : m_master (master)
   {
      m_master->RegisterEventReceiver(this);
   }

   virtual ~INetworkEventReceiver()
   {
      m_master->UnregisterEventReceiver(this);
   }

   // Called by our m_master object whenever a network event happens
   // Implemented by subclasses to do something useful.
   virtual void NetworkEventReceived(const NetworkEvent & event) = 0;

private:
   INetworkEventGenerator * m_master;
};

Все это прекрасно работает.Тем не менее, теперь есть интерес к использованию этой библиотеки в приложении для iOS через Objective C ++.

Мой вопрос заключается в том, как лучше всего в коде Objective-C ++ реализовать "методы ловушек", такие как NetworkEventReceived(const NetworkEvent & event) выше?Я надеялся, что класс Objective-C ++ может просто создать подкласс INetworkEventReceiver и объявить свой собственный виртуальный метод, как это делает подкласс C ++, но кажется, что Objective-C ++ не поддерживает этот .Каков следующий лучший способ сделать это?

1 Ответ

1 голос
/ 28 мая 2019

Вы можете встроить класс C ++ как ivar в класс Objective-C.Что-то вроде:

// header:
@interface Receiver : NSObject
@end

// .mm:
// declare any methods with C++ typed parameters or return types here so the header
// can be #imported in Objective-C, not just Obj-C++. This class extension 
// can also be moved to an Objective-C++-only header if necessary to get to 
// those methods from multiple .mm files.

@interface Receiver()
- (void) receivedNetworkEvent:(const NetworkEvent& event)event;
@end


struct ConcreteReceiver : INetworkEventReceiver
{
  __weak Receiver* target;

  virtual void NetworkEventReceived(const NetworkEvent& event) override;

};

void ConcreteReceiver::NetworkEventReceived(const NetworkEvent& event)
{
  [this->target receivedNetworkEvent:event];
}


@implementation Receiver
{
  ConcreteReceiver receiverShim;
}

- (instancetype)init
{
  self = [super init];
  if (self != nil)
  {
    self->receiverShim.target = self;
  }
  return self;
}

- (void) receivedNetworkEvent:(const NetworkEvent& event)event
{
  // Do the thing
}

@end

Это немного неловко, особенно с большими интерфейсами, но это работает.Обратите внимание, что объект C ++ содержит ссылку __weak на содержащий его объект Objective-C, чтобы избежать утечек.

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