Ошибка приведения типов в C ++

Возможный дубликат:
недействительные указатели: разница между C и C ++

Привет, у меня есть следующая функция:

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
}

Приведенный выше код хорошо работает с C, но не компилируется на C ++. Я получаю следующую ошибку:

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

Я не могу понять причину этой ошибки. Есть идеи, почему эта ошибка возникает, когда я меняю расширение файла на CPP и компилирую?


person webgenius    schedule 04.10.2012    source источник
comment
Вам нужно опубликовать больше кода - например, объявления функций и объектов.   -  person Konrad Rudolph    schedule 04.10.2012
comment
Разве это не потому, что void* неявно конвертируется в C, но не в C++?   -  person verdesmarald    schedule 04.10.2012
comment
В C ++ недопустимо преобразовывать указатель данных (например, void*) в указатель на функцию (например, void* (*)(void*)). Однако многие компиляторы позволят вам уйти от этого. Я бы либо удалил, либо скорректировал состав task2, который вы делаете, когда звоните thread_add_work. Я бы также удалил (void*) состав a, который, кажется, бесполезен. Слишком много бросков - всегда плохой знак, они просто скрывают ошибки.   -  person john    schedule 04.10.2012
comment
что такое task2? это функция?   -  person weima    schedule 04.10.2012
comment
Только что обновил содержание задачи2 в вопросе   -  person webgenius    schedule 04.10.2012


Ответы (2)


Вы должны изменить подпись task2, чтобы она соответствовала типу аргумента thpool_add_work:

void* task2(void* a)

Вызов, который создает поток, станет

thpool_add_work(threadpool, task2, &a);

предполагая, что a равно int.

Если вам нужно использовать аргумент task2, вы можете сделать следующее:

int ia = *(int*)a;

Обновите, чтобы ответить на комментарий OP

thpool_add_work по какой-то причине ожидает функцию с void* аргументом. Таким образом, вы можете передать любой параметр в функцию потока, хотя и небезопасным для типа способом.

Вы передаете адрес параметра, преобразованного в void*, в качестве третьего аргумента thpool_add_work. После этого вы переводите указатель на void обратно к указателю на ожидаемый тип параметра и разыменовываете его, чтобы получить значение параметра. Я привел пример для int a выше, теперь как он будет искать поплавок:

void* test3(void* a)
{
float fa = *(float*)a;
.....
return NULL;
}
person Andrey    schedule 04.10.2012
comment
task2 нужно преобразовать его в int, а task3 нужно преобразовать void * в float. Я не уверен, как поможет изменение параметра на void * a. Не могли бы вы уточнить? - person webgenius; 04.10.2012
comment
@webgenius: ответ обновлен - person Andrey; 04.10.2012

Попробуй это

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

C автоматически преобразует void* в любой тип, а C ++ - нет.

Вы можете улучшить код с помощью 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
}
person john    schedule 04.10.2012