Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What kinds of C++ functions can be placed in a C function pointer?

I have a C library that uses a struct of function pointers for callbacks. The callbacks will be called from C code.

extern "C" {
typedef struct callbacks_t {
    void (*foo) (const char*);
    int  (*bar) (int);  
} callbacks_t;
}// extern C

What kinds of C++ functions can I safely place in those function pointers to be called from the C library? Static member functions? Fully specified template functions? Non-capturing Lambdas?

g++ seemingly lets me use all of the above, but I question the safety when different calling conventions and language bindings are used for C and C++ functions.

like image 929
user1526370 Avatar asked Apr 29 '16 15:04

user1526370


1 Answers

I have a C library that uses a struct of function pointers for callbacks. The callbacks will be called from C code.

A C library only understands C. So you can only pass back things that are explicitly supported and understood by C.

Since there is no definition of calling conventions for any function types in C++ you can not explicitly pass back C++ functions. You can only pass back C function (those explicitly declared with extern "C") and guarantee that they are compatible.

Like all undefined behavior this may seem to work (like passing back normal C++ functions or static members). But like all undefined behavior it's allowed to work. You just can't guarantee that it's actually correct or portable.

extern "C" {
    typedef struct callbacks_t {
        void (*foo) (const char*);
        int  (*bar) (int);  
    } callbacks_t;

    // Any functions you define in here.
    // You can set as value to foo and bar.

}// extern C

What kinds of C++ functions can I safely place in those function pointers to be called from the C library?

Static member functions?

No. But this happens to work on a lot of platforms. This is a common bug and will bite people on some platforms.

Fully specified template functions?

No.

Non-capturing Lambdas?

No.

g++ seemingly lets me use all of the above,

Yes. But it is assuming that you are passing to objects that are built with the C++ compiler (which would be legal). As C++ code will use the correct calling convention. The problem is when you pass these things to a C library (pthreads springs to mind).

like image 144
Martin York Avatar answered Sep 19 '22 15:09

Martin York