Возможный дубликат:
Функция pthread из класса
Я пытаюсь создать поток с подпрограммой запуска, но g ++ не нравится мой синтаксис.
class myClass
{
void* myFunction(void* myArg)
{
// some code, useless here
}
void start()
{
pthread_t thread_id;
int* fd;
//Some code, useless here.
pthread_create(&thread_id, 0, &myFunction, (void*) fd);
}
}
Во время компилятора g ++ говорит мне, что ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function. Say '&myFunction'
,
Не может конвертировать void (myClass::*) (void*)
в void* (*) (void*)
для аргумента 3 из pthread_create
,
Любая идея ?
Вам нужно будет объявить myFunction как статическую, чтобы ее можно было рассматривать как обычную функцию.
Вы не можете использовать обычный член функции в качестве подпрограммы потока. Причина в том, что такой член функции требует вызова контекста — this
указатель объекта, который недоступен для pthread
кишок.
Сделать такую функцию членом static
или просто бесплатная функция.
Вы не можете передать указатель на нестатический метод. Возможно, вы захотите использовать прокси-функцию, передав указатель на ваш экземпляр в качестве параметра pthread_create и сделав оттуда вызов myFunction
Как сказал компилятор, вы должны использовать статическую функцию с pthread, что-то вроде этого должно работать:
class myClass
{
static void startThread(void* context)
{
((myClass*)context)->myFunction()
}
void myFunction()
{
// some code, useless here
}
void start()
{
pthread_t thread_id;
//Some code, useless here.
pthread_create(&thread_id, 0, &startThread, this);
}
}
Также вы можете использовать структуру как контекст, в котором вы можете передать этот и другие аргументы, если это необходимо.
Вы можете либо сделать вашу функцию статичной, либо использовать небольшой обходной путь для вызова функции из вашего класса.
void *callMyFunction(void *f)
{
reinterpret_cast<myClass*>(f)->myFunction();
return (NULL);
}
class myClass
{
void* myFunction()
{
// some code, useless here
}
void start()
{
pthread_t thread_id;
int* fd;
//Some code, useless here.
pthread_create(&thread_id, 0, &callMyFunction, (void*) this);
}
}
Если вы хотите передать параметры myClass::myFunction
, вам нужно будет создать небольшую структуру, как это
struct s_param
{
void *ptr;
int param1;
char param2;
/* other variables */
};
callMyFunction
станет
void *callMyFunction(void *bundle)
{
reinterpret_cast<myClass*>(bundle->ptr)->myFunction(bundle->param1, bundle->param2/*, ...*/);
return (NULL);
}
Как указано вашим компилятором pthread_create
ожидать void* (*)(void*)
но вы предоставляете функцию, которая имеет очень похожий, но другой синтаксис:
Каждая функция класса, который не является static
имеет скрытый параметр с именем this
типа class*
так что теперь ваша функция void* (*)( class*, void* )
это не соответствует ожиданиям pthread_create
, Вы должны предоставить функцию с той же архитектурой.
Также, если у вас была такая функция, как void* someFunction()
в вашем классе это может быть соответствие для функции, которая ожидается pthread_create
Конечно, это не разрешено компилятором, и на это также есть причина. Причина в соглашении о вызовах, означающем, как параметры, передаваемые в функцию, компилятору C ++ разрешено передавать this
в реестрах! поэтому он не будет соответствовать функции, ожидаемой pthread_create
, Это может быть решено некоторыми компиляторами, которые позволяют вам выбирать соглашение о вызовах для вашей функции, но это не является стандартным, поэтому лучше всего написать прокси-функцию как:
static void* my_thread_routine_proxy(void* param) {
static_cast<my_class*>(param)->my_thread_routine();
}
Но если вам нужно передать больше параметров, вы должны создать для него структуру и передать свои параметры в этой структуре, но не забывайте, что переданная структура должна оставаться действительной до тех пор, пока ваша функция на самом деле не будет вызвана как новый поток. Так что это должен быть глобальный или динамически размещаемый объект