Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call a C++ function pointer from C?

Tags:

c++

c

I was successfully to finally be able to use TUI header from PDcurses library in my C++ project in a previous post here.

now in my class I am including the C header:

#include "tui.h"

tui is in C and has this definition for menu:

typedef struct 
{
    char *name; /* item label */
    FUNC  func; /* (pointer to) function */
    char *desc; /* function description */
} menu;

so in MainView.cpp I have:

void sub0()
{
    //domenu(SubMenu0);
}

void sub1()
{
    //domenu(SubMenu1);
}


void MainView::showMainMenu()
{
    menu MainMenu[] =
    {
        { "Users", sub0, "Manage Users" },
        { "Accounts", sub1, "Manage Accounts" },
        { "Items", sub1, "Manage Items" },
        { "Staff", sub1, "Manage Staff" },
        { "", (FUNC)0, "" }  
    };
    startmenu(MainMenu, "Library System 1.0");
}

this is working as expected.

The problem is that i need to make calls on my class methods in sub0() and sub1().

I tried to define C++ methods for my class to try and replace sub0 and sub1 with:

void MainView::sub0()
{
    //domenu(SubMenu0);
}
void MainView::sub1()
{
    //domenu(SubMenu1);
}

the compiler is throwing this error:

error C2440: 'initializing' : cannot convert from 'overloaded-function' to 'FUNC'
None of the functions with this name in scope match the target type

what is the best way of passing those function pointers to the C code and get rid of that error?

thanks

like image 897
Bach Avatar asked Jun 21 '10 01:06

Bach


2 Answers

C++ class objects have a "this" pointer, which is sort of invisibly passed as the first argument to a class member function. That means you can't use a non-static member function for a C-style function pointer that takes 0 arguments.

So solve this, you have a few choices. I'd need more detail before telling you which one to go with.

  • Make the functions you want to use in the C code static.
  • Use boost or tr1 or some other C++ library that allows binding member functions with their this pointer. With boost, this would look like:

    { "Users", boost::bind(&MainView::sub0, this), "Manage Users" },
    
  • You might be able to modify your code to pass around a reference to the class object along with these function pointers. If so, you can then invoke your callbacks directly on the object you want. It looks like you're dealing with a window manager though, and so you probably won't be able to make the changes needed for this approach to work.

  • Probably what you will end up doing is some sort of work around, involving storing the pointer to the object you're using somewhere and then writing small stub functions which access this pointer and then call a member function on it. Some (dare I say, most) window managers allow you to include a pointer to arbitrary data with the callback for this purpose.
like image 146
SoapBox Avatar answered Nov 18 '22 17:11

SoapBox


I don't think it's possible to pass a non-static member function as a FUNC pointer. As the compiler will pass a this pointer to all non-static member function.

You have 2 choices:

  1. Keep your sub0 and sub1 in class and make them static
  2. Move your sub0 and sub1 out of class. And pass a pointer to your class(aka this) to them in the case you need to access other member variables/functions in sub0/sub1.
like image 27
Jason Avatar answered Nov 18 '22 18:11

Jason