1

I am trying to convert a C code to C++. In my .c file I've definitions like this:

void services(void);
void transfers(void);

Further more, a thread will initialize the above two like this:

_beginthread((void*) services,0,NULL);
_beginthread((void*) transfers,0,NULL);

When I try to compile, I got the following error at both the places above like this:

Conversion from void* to pointer to non-void required an Explicit cast: Cannot convert parameter 1 from void* to void(_cdecl*)(void*)

I am confused about this, hope you guys make it clear for me :-)

user2754070
  • 509
  • 1
  • 7
  • 16
  • 1
    you can simply use `extern "C"` linkage and leave your C code alone – mvp Sep 06 '13 at 11:12
  • According to the `_beginthread` documentation on MSDN, the parameter for the thread routine is a `void *` not a `void`. Perhaps C is more forgiving about that. – lurker Sep 06 '13 at 11:13
  • What is the signature for _beginthread function? – Patrik Beck Sep 06 '13 at 11:13
  • Just a passing comment: type casts are **always** explicit. A cast is something you write in your source code to tell the compiler to do a conversion. When you write a cast, the **conversion** is explicit; when the compiler does a conversion without a cast the conversion is implicit. – Pete Becker Sep 06 '13 at 13:20

3 Answers3

3

The solution is to use functions of the correct type and not cast them. Ignore the parameter if it's not relevant to the code.

void services(void*);
void transfers(void*);

_beginthread(services, 0, NULL);
_beginthread(transfers, 0, NULL);

If you absolutely can't change the functions, e.g. if you don't have access to the sources, use wrappers:

void correct_services(void*) { services(); }
_beginthread(correct_services, 0, NULL);

The compiler is helping you here - don't try to work around it by lying to it.

molbdnilo
  • 64,751
  • 3
  • 43
  • 82
1

It looks like you are trying to convert from C++ calling standard to C calling standard. cdecl stands for C declaration. To manually define a function to be cdecl you can use void _cdecl funct();

liftarn
  • 429
  • 3
  • 21
0

Try:

_beginthread((void(_cdecl*)(void*)) services, 0, NULL);

What you were doing was explicitly casting the function pointer to a non-function pointer type (void *). This was OK. But the _beginthread function expects as its first parameter a function pointer of the correct type mentioned in the error message. So you need to fix your cast.


If you're about to downvote this answer, I'd appreciate to know the reason why. I know it would be much better if user2754070 wanted to change the prototype of services (see my comments below). However, what I'm suggesting works (the answer was accepted) and, as far as I know, it is safe and standard practice in C libraries spawning threads. If you think it's not, please explain why and I'll consider deleting the answer.

nickie
  • 5,608
  • 2
  • 23
  • 37
  • Casting a function is a terrible idea, you're likely to leave the call stack in a corrupt state. – molbdnilo Sep 06 '13 at 11:25
  • @molbdnilo, please explain and provide an answer. Passing generic function pointers to functions like `_beginthread`, `pthread_create` etc. is standard procedure and may involve type casting. I don't understand why this is not safe. – nickie Sep 06 '13 at 11:29
  • @molbdnilo, your answer is right (and +1) but say, for the sake of an argument, that you cannot change the prototype for `services`. What's wrong with what I'm suggesting? – nickie Sep 06 '13 at 11:38
  • One technical reason is that if the called function gets passed too few arguments, "funny" things will happen. – molbdnilo Sep 06 '13 at 12:01
  • @molbdnilo, I understand that casting function pointers in general is a bad thing. But for this particular case, there's no way to pass fewer parameters to `services`, as it expects none. In fact, it will be called with one parameter (`NULL`), which will be handled OK (it has to, for backwards compatibility with a lot of horrible C code that exists out there). So let's talk about this case; is this casting bad? – nickie Sep 06 '13 at 12:07