1

I am a C programmer (on linux), but now I have a project on C++, and have a question.

Here is sample code

g_action.sa_sigaction = (void(*)(int,siginfo_t*,void*))&FlashWork::Disconnect_action; 

When I try to compile this on x86, it works fine, but on arm I get the following error

error: converting from void (FlashWork::*)(int, siginfo_t*, void*) to void (*)(int, siginfo_t*, void*)

What am I doing wrong?

Charles
  • 50,943
  • 13
  • 104
  • 142
evghin
  • 47
  • 5
  • The error message in the header doesn't match the code and the error message in the question text. The header has an extra `*` in the return type of the destination type, `void*` rather than `void`. The question body is the correct function type for sigaction. – Steve Jessop Mar 29 '12 at 12:34

3 Answers3

3

"Pointer to members" are not compatible with "pointers to functions", unless it's a static member. The reason is that a pointer to member needs an object (a FlashWork object) in your case.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • 1
    Actually even if it's `static` it still won't have `extern "C"` linkage required for sa_sigation. Most implementations allow it, but it's not mandated. – Flexo Mar 29 '12 at 12:31
  • @awoodland, isn't `extern "C"` related to name-mangling? How is that a problem with function pointers (in which you have the function's address, and not the name anymore) – Shahbaz Mar 29 '12 at 12:38
  • @Shahbaz: Theoretically, it can also affect calling conventions, and it _is_ considered in overload resolution. Which is why C++ defines two overloads of `qsort`. – MSalters Mar 29 '12 at 12:39
  • @Shahbaz - it's not just name mangling, they're still distinct types in theory. http://stackoverflow.com/questions/2068022/in-c-is-it-safe-portable-to-use-static-member-function-pointer-for-c-api-call and http://stackoverflow.com/a/592205/168175 – Flexo Mar 29 '12 at 12:39
  • Good to know, I had never though about it – Shahbaz Mar 29 '12 at 13:02
1

Your function is a member function that returns a void. It should be a non-member function (or a static member function) that returns a void *.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
1

Besides the fact the return value of the functions are different, you should know that in C++, when you have a member function (which is not static):

void (FlashWork::*)(int, siginfo_t*, void*)

The real signature (the one a C programmer likes to see) is this:

void (*)(FlashWork *, int, siginfo_t *, void *)

That FlashWork * parameter is a hidden pointer which can be referred to by this.

Therefore,

void (FlashWork::*)(int, siginfo_t*, void*)

and

void (*)(int, siginfo_t*, void*)

have different number of arguments.

Shahbaz
  • 46,337
  • 19
  • 116
  • 182
  • Putting the "extra parameter" first might be misleading. You can't convert `&FlashWork::Disconnnect_action` to `void (*)(FlashWork *, int, siginfo_t *, void *)` either, so that's not the "real" signature. On any given implementation the calling convention for member functions may or may not look the same as if they were free functions with `this` passed as the first parameter. – Steve Jessop Mar 29 '12 at 13:34
  • @SteveJessop, right. I just wanted to point out that `this` is also a parameter. I always thought it would be the first parameter though. Good to know. – Shahbaz Mar 29 '12 at 15:12
  • On Windows/x86 for example, all parameters of non-member calls are passed on the stack (unless the fastcall convention is used, but for public API calls it isn't). `this` is passed in the register ECX, as is the first parameter when using fastcall. But in thiscall all (other) parameters are on the stack, whereas in fastcall the second parameter goes in EDX. So the calling convention with `this` isn't the same as adding it as the first parameter to either of the other two calling conventions. – Steve Jessop Mar 30 '12 at 09:33