2

I have a C library which use this function prototype, I want to use it in C++

int mlx_key_hook(void *win_ptr, int (*funct_ptr)(), void *param);

but in reality the function asked is

int funct_ptr(int keycode, void *param);

In fact I have this problem: Why put void in params?

Then, I ask you how can I call this function with the appropriate C++ funct_ptr ?

Or have I to re-compil this lib after having changed the funct_ptr prototype ?

This doesn't work:

mlx_key_hook(win_ptr, [](int keycode, void *param) -> int {

    return 0;

}, NULL);

This work but that's not what I want:

mlx_key_hook(win_ptr, []() -> int {

    return 0;

}, NULL);
Community
  • 1
  • 1
Kerollmops
  • 303
  • 4
  • 15
  • The C library is not expecting the 2-arg function pointer, so that is the reason the first one does not work. You have to ask for a new function accepting a function with an `int` and a `void*` parameter in the C lib. – Gábor Bakos Dec 21 '14 at 11:34
  • You'll have to cast the function pointer. – Alan Stokes Dec 21 '14 at 11:34

1 Answers1

6

The best solution would be to recompile your C++ code with a header that uses an appropriate function prototype, i.e.

int mlx_key_hook(void *win_ptr, int (*funct_ptr)(int keycode, void *param), void *param);

Then the code snippet with a lambda that takes two parameters will compile.

Another solution would be to use reinterpret_cast. Although it is not allowed to call a function with a reinterpreted signature (undefined behavior) casting a reinterpreted pointer back to its original signature before the call is allowed.

typedef int (*funct_ptr_good)(int, void *);
typedef int (*funct_ptr_bad)();

void foo(funct_ptr_bad fb) {
    // This is a C++ version of what your C library does
    funct_ptr_good fg = reinterpret_cast<funct_ptr_good>(fb);
    fg(12345, NULL);
}

int main() {
    funct_ptr_good fg = [] (int key, void * ptr) -> int {
        cout << key << " " << ptr << endl;
        return 0;
    };
    // foo expects a pointer that takes no parameters, in the same way that your C library does
    foo(reinterpret_cast<funct_ptr_bad>(fg));
    return 0;
}

The above prints 12345 0 (demo).

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • Hoooon! You do a good answer ! GG ! I will try to do that, thank you :) – Kerollmops Dec 21 '14 at 11:55
  • When you say ***The best solution would be to recompile your C++ code***, you mean ***The best solution would be to recompile your C library***, no ? – Kerollmops Dec 21 '14 at 11:57
  • @Kerosene Recompiling C library with the new prototype will not change anything, because the trick "function declared with empty parentheses takes anything I pass" already works in C. The header for that function that you include in your C++ code is what's telling C++ of C library's expectations. C++ interprets the expected signature differently, though: empty parentheses mean strictly "no parameters" to C++. So it's only C++ code that needs the right signature, not the C code. – Sergey Kalinichenko Dec 21 '14 at 12:03
  • That work perfectly with `reinterpret_cast(funct_ptr)` thank you very much ! Have a good day :) – Kerollmops Dec 21 '14 at 12:10