79373253

Date: 2025-01-21 05:17:44
Score: 1
Natty:
Report link

There is a dangerous way to do this with an instance. It requires disabling a warning/error with -Wno-dangling-pointer, which indicates the danger.

extern "C" {
   void set_update_callback(void (*p)(struct Data*)) //
   {}; // function body to test it all compiles
}

class MyDataClass {
private:
   void handle_data(struct Data* d) {
   }

public:
   // Subscribe to the data provider using my handler function
   static void subscribe(MyDataClass& my_data_class) {
   // set pointer to an instance of self and subscribe to C API
      mSelf = &my_data_class;
      ::set_update_callback(&data_handler_callback);
   }
   static inline MyDataClass* mSelf{};    
   static void data_handler_callback(struct Data* d) {
      MyDataClass::mSelf->handle_data(d);
   }
};

auto main() -> int {
   MyDataClass mdc{};
   MyDataClass::subscribe(mdc);
   return 0;
}

I don't recommend this, but I have used something similar for handling interrupts in a microcontroller system. The other answer using only one instance would be preferred.

Here is another approach using an anonymous namespace to avoid creating global entities. You can only access it in the source file, but MyDataHanler is outside the namespace, so it can be accessed. (I can see the downvotes now. <shrug.>)

struct MyDataHandler {
   void handle_data(struct Data* d);
   static inline MyDataHandler* self;
};

namespace {
   extern "C" {

   void set_update_callback(void (*p)(struct Data*)) //
      { }; // function body to test it all compiles
   }

   void data_handler_callback(struct Data* d) {
      MyDataHandler::self->handle_data(d);
   }

   void subscribe(MyDataHandler& mdh) {
      MyDataHandler::self = &mdh;
      ::set_update_callback(&data_handler_callback);
   }
}

auto main() -> int {
   MyDataHandler mdh;
   subscribe(mdh);
   return 0;
}
Reasons:
  • RegEx Blacklisted phrase (2): downvote
  • Long answer (-1):
  • Has code block (-0.5):
  • Low reputation (0.5):
Posted by: Rud48