【问题标题】:What's the proper way to receive C++ virtual-method calls into an Objective-C++ application?将 C++ 虚拟方法调用接收到 Objective-C++ 应用程序的正确方法是什么?
【发布时间】:2019-05-28 00:57:52
【问题描述】:

我有一个可移植的 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;
};

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

我的问题是,Objective-C++ 代码实现像上面的NetworkEventReceived(const NetworkEvent & event) 这样的“挂钩方法”的最佳方式是什么?我希望 Objective-C++ 类可以简单地继承 INetworkEventReceiver 并声明自己的虚拟方法,就像 C++ 子类那样,但似乎 Objective-C++ doesn't support that。实现这一目标的下一个最佳方法是什么?

【问题讨论】:

    标签: inheritance callback objective-c++ virtual-functions


    【解决方案1】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-17
      • 1970-01-01
      • 1970-01-01
      • 2013-06-18
      • 1970-01-01
      • 2017-05-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多