-1

Dear reader
I'm making a library module for a process scheduler. Default the scheduler has 8 entries 0..7 and the functions/processes in the scheduler are called using a function pointer. Written as a normal C program it works as expected. But now I want to configure the function pointer in the .h file I have compiler errors pointing at the function pointers. I have a problem with the function pointer located at &scheduler::dummy in the proclist[8], they generate me errors and I don't know how to solve them.

Can some one advice me what to do.

The error the produce are

scheduler.cpp:9: In file included from

Error compiling libraries

scheduler.h: 56:87: error:
cannot convert 'void (scheduler::*)(uint8_t*) {aka void (scheduler::*)(unsigned char*)}' to 'void (*)(uint8_t*) {aka void (*)(unsigned char*)}' in initialization 
           { 7, 3900  ,10000 ,0,PROC_ACT ,&scheduler*: dummy7 , &proclist[7].val ,65  ,1}}; 
\\process table entry 7
Build failed for project 'Scheduler'

and 7x time this error.

scheduler.h: 56:87: error: 
 cannot convert 'void (scheduler::*)(uint8_t*) {aka void (scheduler::*)(unsigned char*)}' to 'void (*)(uint8_t*) {aka void (*)(unsigned char*)}' in initialization

The code in the .h file is the following
(line 56 is indicaded in the code block)

 //process structure
typedef struct  process_t{                                  // Start of the Process scheduler structure
    uint8_t                         index               ;   // index of this process in the  process structure array
    uint32_t                        starttime           ;   // Absolute start and next call time of the function
    uint32_t                        delta               ;   // Time between the function to be called
    uint32_t                        exetime             ;   // Time it takes to execute the function
    uint8_t                         stat                ;   // skip, delete, change, active
    void                          (*pt2function)(uint8_t*) ;// Pointer to function to be called
    uint8_t                        *valptr              ;   // Pointer to value given as function Parameter
    uint8_t                         val                 ;   // Default value being pointed at
    uint8_t                         nextprocess         ;   // Index to next process in the process structure array
};

class scheduler {

    public:
            void    run();
            void    man  (uint8_t *); 
            void    dummy(uint8_t *);


        //  Processes 0,1..5 arrays of Process structs.
            process_t proclist[8]   =   {{0, ROLLOFFSET ,0     ,0,PROC_ACT ,&scheduler::man     , &proclist[0].val ,INIT    ,1} ,   //Initialise(), Run ones in the process list
                                        { 1, 3000       ,2237  ,0,PROC_ACT ,&scheduler::dummy   , &proclist[1].val ,65      ,2} ,   //process table entry 1
                                        { 2, 3100       ,2718  ,0,PROC_ACT ,&scheduler::dummy   , &proclist[2].val ,66      ,3} ,   //process table entry 2  
                                        { 3, 3200       ,3141  ,0,PROC_ACT ,&scheduler::dummy   , &proclist[3].val ,67      ,4} ,   //process table entry 3 
                                        { 4, 3300       ,2237  ,0,PROC_SKP ,&scheduler::dummy   , &proclist[4].val ,65      ,5} ,   //process table entry 4
                                        { 5, 3400       ,2718  ,0,PROC_SKP ,&scheduler::dummy   , &proclist[5].val ,66      ,6} ,   //process table entry 5
                                        { 6, 3500       ,3141  ,0,PROC_SKP ,&scheduler::dummy   , &proclist[6].val ,67      ,7} ,   //process table entry 6
/*===Line 56 ==>*/                      { 7, 3900       ,10000 ,0,PROC_ACT ,&scheduler::dummy   , &proclist[7].val ,65      ,1}};   //process table entry 7

            // and other functions if needed

    private:
            int8_t   n, cnt;
            uint32_t    mmillis();
};
molbdnilo
  • 64,751
  • 3
  • 43
  • 82
wogoos
  • 21
  • 3
  • 4
    A pointer to a member function is *not* the same as a pointer to a non-member function. The big difference is that a member function needs an object to be called with, and non-member function doesn't. Read about [`std::function`](http://en.cppreference.com/w/cpp/utility/functional/function), [`std::bind`](http://en.cppreference.com/w/cpp/utility/functional/bind), and [lambda expressions](http://en.cppreference.com/w/cpp/language/lambda). – Some programmer dude Feb 09 '18 at 06:32
  • The error tells you that you function signature is wrong and what it expects. "(scheduler::)(uint8_t) ". Calling the function afterwards is a different matter to which "some programmer dude" has provided the answer for. – Aleks Feb 09 '18 at 06:55
  • One option is to make `scheduler::nan` and `scheduler::dummy` static member functions (or global functions). If that is not possible then you have to redesign your code along the lines described in the comments above. – john Feb 09 '18 at 07:02
  • I tried to fix your formatting. I'm not sure if it looks exactly like your original, but at least the types are visible now. – molbdnilo Feb 09 '18 at 08:02
  • 1
    Possible duplicate of [Function pointer to member function](https://stackoverflow.com/questions/2402579/function-pointer-to-member-function) – SirGuy Feb 09 '18 at 15:07

2 Answers2

2

The non-static member function have a hidden pointer to an instance of the class, this, so Pointers to Member Functions need an object and you cannot use them like normal function pointers.

Depending on your design you can eother

  1. make the methods static:

    static void    man  (uint8_t *); 
    static void    dummy(uint8_t *);
    

    Maybe you'll have to add one more argument to pass a reference to the scheduler or the process_t instance.

  2. or change pt2function to pointers to member function:

    class scheduler;
    
    //process structure
    struct  process_t{                            // Start of the Process scheduler structure
        // ...
        void  (scheduler::*pt2function)(uint8_t*) ;// Pointer to function to be called
        // ...
    

    And you can later use these pointer to member functions from scheduler like this:

    class scheduler {
    // ...
    void run() {    
        (this->*proclist[0].pt2function)(proclist[0].valptr);
    }
    

Playground

Mihayl
  • 3,821
  • 2
  • 13
  • 32
  • I implemented the 2nd solution. It generates one error pointing to how I call the scheduled function/process from the scheduler. In "C" I use the following line : proclist[0].pt2function(proclist[0].valptr); that worked. I now have for this specific line the following error scheduler.cpp: 18:45: error: must use '.*' or '->*' to call pointer-to-member function in '((scheduler*)this)->scheduler::proclist[0].scheduler::process_t::pt2function (...)', e.g. '(... ->* ((scheduler*)this)->scheduler::proclist[0].scheduler::process_t::pt2function) (...). Can you advice again how to call the Function – wogoos Feb 09 '18 at 14:58
0

I implemented the 2nd solution and that works as long as I call methods with in the scheduler class. The scheduler however will call methods from other classes. Below and example were I try to call a method called "wifi_manager::statemachine" which manages a wifi connection and is called every 1 second. This pointer assignment fails because this statemachine method is not part of the schedule class but is part of a wifi_manager class. What do I need to do to have my proclist[8] to contain pointers to various methods in various classes which are called by a method "run" in the schedule class and how do I call these functions/methods.

Hope someone can help me forward on this

/*
    scheduler.ino - tested at 7-2-2018
    Created by Oscar Goos, January 2018
    Test on Platform ESP8266-e12.
    Released into the public domain.
    Program size: 250,264 bytes (used 24% of a 1,044,464 byte maximum) (9.02 secs)
    Minimum Memory Usage: 32716 bytes (40% of a 81920 byte maximum) */

    #include "stdio.h"
    #include "scheduler.h"
    #include "wifi_manager.h"

    scheduler scul;

    void setup()
    {
        Serial.begin(115200, SERIAL_8N1);
        Serial.printf("\n");
        scul.proclist[1].pt2function=&wifi_manager::statemachine; // Assign pointer to proclist[1]
      /* add setup code here */
    }

    void loop()
    {
        scul.run();
      /* add main program code here */
    }
wogoos
  • 21
  • 3