0

I need to change the prototype of a function pointer of a class. So, I was hoping inheriting it and doing the following would work, but it doesn't ("invalid use of non-static member function 'void B::myIntCallback(unsigned int)"):

class A {
  public:
    typedef void (*intCallback_t)(unsigned int myInt);
    A(intCallback_t intCallback) {}
};

class B : A {
  public:
    typedef void (*charCallback_t)(unsigned char myChar);
    B(charCallback_t charCallback) : A(this->myIntCallback) {
        charCallback_ = charCallback;
    }

  private:
    charCallback_t charCallback_;
    void myIntCallback(unsigned int myInt) {
        charCallback_((unsigned char)myInt);
    }
};

Does anybody know how I can solve this? I can't change class A.

arnold_w
  • 59
  • 9
  • `void (*)(unsigned int)` != `void (A::*)(unsigned int)`. – Jarod42 Oct 21 '22 at 11:47
  • `&ClassName::mehtodName` is syntax for a member function pointer, though thats only the immediate error. Please include the complete error message in the question – 463035818_is_not_an_ai Oct 21 '22 at 11:48
  • `B::myIntCallBack` reuqires a `B` object to be called. `A`s constructor expects a pointer to a free function. – 463035818_is_not_an_ai Oct 21 '22 at 11:51
  • Jarod42: I agree they are not the same, but I don't know how that solves my compile error. – arnold_w Oct 21 '22 at 11:59
  • 463035818_is_not_a_number: The complete error message is within quotes in the question. – arnold_w Oct 21 '22 at 11:59
  • Stephen Newell: No, that question doesn't touch the subjects of inheritance and constructor. – arnold_w Oct 21 '22 at 12:00
  • 463035818_is_not_a_number: So, what's the solution then? – arnold_w Oct 21 '22 at 12:00
  • I think you can just cast like this :A((intCallback_t) charCallback) and remove myIntCallback function. Because in your case both signatures are ABI compatible – jenkas Oct 21 '22 at 12:19
  • jenkas: I simplified the real function pointers to make it easy to understand my problem. In reality, the prototypes are very different. – arnold_w Oct 21 '22 at 12:21
  • Depending on how desperate you are, you could have a look at this answer: https://stackoverflow.com/a/18422878/5523775. It basically uses template meta-programming to store a std::function in a singleton and make it accessible in a static context to retrieve a function pointer from it. – Peter H Oct 21 '22 at 12:27
  • Well, if you have some logic inside, that does convert parameters from one signature to another, you will have to store somehow the instance of B per each callback, which will be very tricky, because your callback must be static. If you can wrap the call to callback, you can pass B->this via thread_local variable, and then access it in static function – jenkas Oct 21 '22 at 12:31
  • @arnold_w can you write an example how you call the callback? It very depends on - if you have access to the caller logic or not – jenkas Oct 21 '22 at 12:46
  • jenkas: You see it here, just search for pxTimer->pxCallbackFunction( https://github.com/cnoviello/mastering-stm32/blob/master/nucleo-f070RB/Middlewares/FreeRTOS/timers.c This is then wrapped in a class where the TimerHandle_t object has been made private and I'm not allowed to change this class. – arnold_w Oct 21 '22 at 13:12
  • This callback receives TimerHandle_t which is void *, that means you can pass anything you want, so you do not have to change signature of function, it already most generic as possible – jenkas Oct 21 '22 at 13:20
  • jenkas: I'm not allowed to go inside the FreeRTOS files and change the argument that's being passed to the callback. – arnold_w Oct 21 '22 at 13:31

1 Answers1

0

You are trying to pass a member function (B::myIntCallback) to a function pointer argument. Since the member function needs an object to be called on, his would require some kind of capturing, e.g. a lambda capturing this or an std::bind expression. Unfortunately, neither is possible with a plain function pointer, see also Passing capturing lambda as function pointer.

If possible, you may want to consider changing the class A to accept either a std::function or a template argument as the type of the callback. See also Should I use std::function or a function pointer in C++?.

Peter H
  • 475
  • 5
  • 14