2

Possible Duplicate:
void pointers: difference between C and C++

Hi I have the following function:

void task2(int a)
{
    printf("  Task 2 running..\n");
    sleep(2);
    printf("  Task 2 exiting..\n");
}

thpool_add_work(threadpool, (void*)task2, (void*)a);

int thpool_add_work(thpool_t* tp_p, void *(*function_p)(void*), void* arg_p)
{
    // some code here
}

The above code works well with C, but does not compile in C++. I'm getting the following error:

error: invalid conversion from ‘void*’ to ‘void* (*)(void*)’
error:   initializing argument 2 of ‘int thpool_add_work(thpool_t*, void* (*)(void*), void*)’

I'm not able to figure out the reason for this error. Any idea why this error crops up when I change the file extension to CPP and compile?

Community
  • 1
  • 1
webgenius
  • 856
  • 3
  • 13
  • 30
  • 1
    You need to post more code – such as the declarations of the functions and objects. – Konrad Rudolph Oct 04 '12 at 06:41
  • Isn't this because `void*` is implicitly convertible in `C`, but not in `C++`? – verdesmarald Oct 04 '12 at 06:42
  • In C++ it's not legal to convert a data pointer (i.e. `void*`) to a function pointer (i.e. `void* (*)(void*)`). However many compilers will let you get away with this. I would either remove or adjust the cast of `task2` you make when you call `thread_add_work`. I'd also remove the `(void*)` cast of `a` which seems to serve no purpose. Too many casts is always a bad sign, it just hides errors – john Oct 04 '12 at 06:42
  • what is task2? is it a function? – weima Oct 04 '12 at 06:45
  • Just updated the content of task2 in the question – webgenius Oct 04 '12 at 06:47

2 Answers2

2

You have to change the signature of task2 to match the type of the thpool_add_work argument:

void* task2(void* a)

The call which creates the thread would become

thpool_add_work(threadpool, task2, &a);

assuming that a is int.

If you need to use the argument of task2, you could do following:

int ia = *(int*)a;

Update to answer the OP comment

thpool_add_work expects a function with void* argument for a reason. In such a way, you can pass any kind of parameter into the thread function, albeit in a type-unsafe way.

You pass the address of the parameter converted to void* as the 3rd argument of thpool_add_work. Afterwards, you cast a pointer to void back to the pointer to your expected parameter type and dereference it to get the value of the parameter. I gave the example for int a above, now how it would look for a float:

void* test3(void* a)
{
float fa = *(float*)a;
.....
return NULL;
}
Andriy
  • 8,486
  • 3
  • 27
  • 51
  • task2 needs to convert it into an int, and task3 need to convert the void* into a float. I'm not sure how changing the parameter to void* a will help. Can you please elaborate? – webgenius Oct 04 '12 at 06:57
  • @webgenius: The answer is updated – Andriy Oct 04 '12 at 07:14
0

Try this

thpool_add_work(threadpool, (void* (*)(void*))task2, (void*)a);

C converts void* to any type automatically, C++ does not.

You could improve the code with a typedef

typedef void* (*worker_func_t)(void*);

thpool_add_work(threadpool, (worker_func_t)task2, (void*)a);

int thpool_add_work(thpool_t* tp_p, worker_func_t function_p, void* arg_p)
{
    // some code here
}
john
  • 85,011
  • 4
  • 57
  • 81