ivan braga
ivan braga

Reputation: 13

'void *' to 'void (*) (bool)' Errors with pointers compiling files in c with a c ++ compiler

First of all, thank you to whoever is reading and to whom you can respond.

This part of code, is part of an interface library gui, totally written in c.

But I'm tempted to compile these written files in c, with a c ++ compiler to be able to integrate into a program I'm doing with wxwidgets.

Within the c files, I have several function calls that have as arguments, pointers to other functions.

 typedef struct {
      void (*fchd_ptr)(bool);   
      uint16_t xpos;         
      uint16_t ypos;          
        ...
        ...
}BUTTON_t;

void BT_SetHandler(BUTTON_t* ptr, void* fchd_ptr)
{
    if (ptr == NULL)
        return;

    ptr->fchd_ptr =  fchd_ptr;  // OK in C, ERROR In C++
}

When I try to compile in C ++, I get this error.

ptr-> fkt_ptr = fkt_ptr;
// error: invalid conversion from 'void *' to 'void (*) (bool)' [-fpermissive]

If I cast an explicit cast.

ptr-> fkt_ptr = (bool *) fkt_ptr;
// error: can not convert 'bool *' to 'void (*) (bool)' in assignment

Any help, and explanation how to solve it will be welcome.

Upvotes: 0

Views: 491

Answers (2)

jxh
jxh

Reputation: 70392

If you change the signature of the function to accept a function pointer that matches the type expected by ptr->fchd_ptr. Then, you would not need to use a cast to complete the assignment.

Based on your question, this would be:

void BT_SetHandler(BUTTON_t* ptr, void (*fchd_ptr)(bool))

However, if you are not sure what the type is for ptr->fchd_ptr, you can make the compiler figure it out for you. Previously, this could only be done with a template function and it would derive a type based on what was passed into the function call at compile time. However, C++.11 provdes decltype, which allows you to enforce the type you want for the function parameter, rather than letting the compiler deduce one from callers of the function.

void BT_SetHandler(BUTTON_t* ptr, decltype(ptr->fchd_ptr) fchd_ptr)

This is fine so long as you are intent on compiling your code with a C++ compiler.

Upvotes: 1

hlt
hlt

Reputation: 6317

Your explicit cast is wrong. You cast to bool * (pointer to object of type bool), when you really should be casting to void (*)(bool) (pointer to function taking a bool and returning nothing).1

If you replace that line by

ptr->fchd_ptr = (void (*)(bool)) fchd_ptr;

it will compile in both C and C++.


If possible, however, you should try to compile your C code in C only - while we might get this one thing working, the two languages are not always fully compatible, and you may well run into trouble down the road. Generally, it is possible to compile C code separately from the C++ parts. If you use extern "C" in your header files, you can simply link the C++ objects and the C objects together, or keep the C part in a separate library (static or dynamic).

Additionally, I would recommend reworking the C API so that it really takes a function pointer all the way through if that is at all possible. Aliasing through void * is ugly and can lead to some really nasty bugs and crashes if you pass in the wrong pointer type.


1 Function pointers are generally very different from object pointers, and it is implementation-defined whether you are even allowed to cast between the two. Here, you want a pointer to a function, not a pointer to an object (like bool* would be a pointer to an object of type bool) so that you can call it later. You can see in your code sample that void (*fchd_ptr)(bool) is the declaration of the variable that you assign to, which makes void (*)(bool) its type. If you find the notation somewhat confusing, cdecl.org is a great way to deal with those convoluted array, pointer and function pointer names that come from C.

Upvotes: 1

Related Questions