将 C++ 虚拟方法调用接收到 Objective-C++ 应用程序的正确方法是什么?

What's the proper way to receive C++ virtual-method calls into an Objective-C++ application?

我有一个可移植的 C++ 网络代码库,它大量使用抽象和半抽象接口 classes,例如像这样的东西:

// 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;
};

一切正常。但是,现在有兴趣通过 Objective C++ 在 iOS 应用程序中使用此库。

我的问题是,Objective-C++ 代码实现 "hook methods"(如上面的 NetworkEventReceived(const NetworkEvent & event))的最佳方法是什么?我希望 Objective-C++ class 可以简单地 subclass INetworkEventReceiver 并声明它自己的虚拟方法,就像 C++ subclass 那样,但是似乎 Objective-C++ doesn't support that。实现此目标的下一个最佳方法是什么?

您可以将 C++ class 作为 ivar 嵌入到 Objective-C class 中。类似于:

// 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++ 对象持有对其包含的 Objective-C 对象的 __weak 引用以避免泄漏。