0

I have a struct defined in C, it takes a pointer to a function. The functions/methods i have defined in C++. How can I pass a reference to the C++ method to the C struct?

This is the error I get: "a value of type "void (Ili9341::)(void , int16_t, int16_t, uint16_t)" cannot be used to initialize an entity of type "void ()(void , int16_t, int16_t, uint16_t) C"

This is the C file

typedef struct Graphics_Display
{
    int32_t  size;              //!< The size of this structure.
    void *displayData;          //!< A pointer to display driver-specific data.
    uint16_t width;             //!< The width of this display.
    uint16_t heigth;            //!< The height of this display.
    void (*callPixelDraw)(void *displayData, int16_t x, int16_t y,
            uint16_t value);    //!< A pointer to the function to draw a pixel on this display.
    void (*callPixelDrawMultiple)(void *displayData, int16_t x, int16_t y,
            int16_t x0, int16_t count, int16_t bPP, const uint8_t *data,
            const uint32_t *pucPalette);    //!< A pointer to the function to draw multiple pixels on this display.
    void (*callLineDrawH)(void *displayData, int16_t x1, int16_t x2, int16_t y,
            uint16_t value);    //!< A pointer to the function to draw a horizontal line on this display.
    void (*callLineDrawV)(void *displayData, int16_t x, int16_t y1,
            int16_t y2, uint16_t value); //!< A pointer to the function to draw a vertical line on this display.
    void (*callRectFill)(void *displayData, const Graphics_Rectangle *rect,
            uint16_t value);    //!< A pointer to the function to draw a filled rectangle on this display.
    uint32_t (*callColorTranslate)(void *displayData, uint32_t  value); //!< A pointer to the function to translate 24-bit RGB colors to display-specific colors.
    void (*callFlush)(void *displayData); //!< A pointer to the function to flush any cached drawing operations on this display.
    void (*callClearDisplay)(void *displayData, uint16_t value); //!<  A pointer to the function to clears Display. Contents of display buffer unmodified
} Graphics_Display;

This is the C++ file

    Ili9341::Ili9341(void){

    }

Graphics_Display Ili9341::ili9341_GetDisplay(){
    Graphics_Display g_sDriver =
    {
        sizeof(tDisplay),
        ili9341_Memory,
    #if defined(PORTRAIT) || defined(PORTRAIT_FLIP)
        LCD_Y_SIZE,
        LCD_X_SIZE,
    #else
        LCD_X_SIZE,
        LCD_Y_SIZE,
    #endif
        ili9341_PixelDraw,
        ili9341_PixelDrawMultiple,
        ili9341_LineDrawH,
        ili9341_LineDrawV,
        ili9341_RectFill,
        ili9341_ColorTranslate,
        ili9341_Flush,
        ili9341_ClearScreen
    };
    return g_sDriver;
}

void Ili9341::ili9341_PixelDraw(void *displayData, int16_t x, int16_t y, uint16_t value){

}

void Ili9341::ili9341_PixelDrawMultiple(void *displayData, int16_t x, int16_t y, int16_t x0, int16_t count, int16_t bPP, const uint8_t *data, const uint32_t *pucPalette){

}

void Ili9341::ili9341_LineDrawH(void *displayData, int16_t x1, int16_t x2, int16_t y, uint16_t value){

}

void Ili9341::ili9341_LineDrawV(void *displayData, int16_t x, int16_t y1, int16_t y2, uint16_t value){

}

void Ili9341::ili9341_RectFill(void *displayData, const Graphics_Rectangle *rect, uint16_t value){

}

uint32_t Ili9341::ili9341_ColorTranslate(void *displayData, uint32_t  value){
    return 0;
}

void Ili9341::ili9341_Flush(void *displayData){

}

void Ili9341::ili9341_ClearScreen(void *displayData, uint16_t value){

}
John
  • 674
  • 1
  • 9
  • 24

3 Answers3

1

You can't get a regular function pointer to a non-static member functions, because the code that called it through the pointer wouldn't be able to specify an object to call it on (basically the value of this).

However, you could use static or non-member functions, and use the displayData field to store a pointer to the object. Something like this:

void ili9341_PixelDrawStatic(void *displayData, int x, int y, int value) {
    static_cast<Ili9341*>(displayData)->ili9341_PixelDraw(x, y, value);
}
void ili9341_PixelDrawMultipleStatic(void *displayData, int x, int y, int16_t count, int16_t bPP, const uint8_t *data, const uint32_t *pucPalette) {
    static_cast<Ili9341*>(displayData)->ili9341_PixelDrawMultiple(x, y, count, bPP, data, pucPalette);
}
// ... and so on

Graphics_Display g_sDriver =
{
    sizeof(tDisplay),
    this,
    // ...
    ili9341_PixelDrawStatic,
    ili9341_PixelDrawMultipleStatic,
    // ... and so on
};

Note that you can't use displayData to point to ili9341_Memory now - but if ili9341_Memory is a member variable of Ili9341 already, then you don't need that.

user253751
  • 45,733
  • 5
  • 44
  • 76
0

Please give more information if this answer is not what you are looking for. It depends if your functions are static or non-static. There is no class declaration in your question.

When you want to pass a function pointer of your class to a struct you have to declare the function pointer in your struct as such class member. See (Ili9341::*callClearDisplay).

class Ili9341
{
  public:

    void ili9341_ClearScreen(void *displayData, int value);
    static void ili9341_ClearScreenStatic(void *displayData, int value);
};

struct Graphics_Display
{
   // declaration of member to contain non-static member function
   void (Ili9341::*callClearDisplay)(void *displayData, int value);

   // declaration of member to contain static member function
   void (*ili9341_ClearScreenStatic)(void *displayData, int value);
};

Graphics_Display op;

// assign non-static member function to struct member
op.callClearDisplay = &Ili9341::ili9341_ClearScreen;

// assign static member function to struct member
op.ili9341_ClearScreenStatic = &Ili9341::ili9341_ClearScreenStatic;

--

Everyone knows what you mean with method but to be really precise the term method is not defined in C++. There are static member functions and non-static member functions.

HelloWorld
  • 2,938
  • 1
  • 22
  • 47
  • @downvoter: Please give feebdack to improve this answer! – HelloWorld Sep 16 '15 at 00:21
  • 1
    If the `struct` is used by C code it's not going to understand `void (Ili9341::*callClearDisplay)()` or how to call it. – Captain Obvlious Sep 16 '15 at 00:22
  • Yes, that is true, but he mentioned C++ in specific. Otherwise the OP should improve his answer by adding the requirement that the "consumer" of the struct just understands C. – HelloWorld Sep 16 '15 at 00:24
  • They also mentioned having "struct _defined in C_" so it's -very_ possible they are interfacing to a C API. Now I don't think that's the case but until you actually know your answer is just as incomplete as the question. – Captain Obvlious Sep 16 '15 at 00:27
  • True - though when he has static member functions, there should be no conversion problem at all (as long as the signatures do match) let's wait until he gives feedback on that. – HelloWorld Sep 16 '15 at 00:33
-2

It seems that you trying to cast member functions (ones that rely on this) to static functions (where this is not available).

Solution: declare such functions as static members of your class. This will require their signature change if you need to pass instance of the class too.

c-smile
  • 24,546
  • 7
  • 54
  • 79